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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -4
  3. data/examples/README.md +1 -1
  4. data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.sh +0 -0
  5. data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.xml +0 -0
  6. data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/root/etc/sysconfig/network/ifcfg-eth0 +0 -0
  7. data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
  8. data/lib/pennyworth/cli.rb +11 -11
  9. data/lib/pennyworth/commands/base_command.rb +8 -8
  10. data/lib/pennyworth/commands/build_base_command.rb +36 -14
  11. data/lib/pennyworth/commands/import_base_command.rb +4 -4
  12. data/lib/pennyworth/commands/list_command.rb +1 -1
  13. data/lib/pennyworth/commands/setup_command.rb +43 -10
  14. data/lib/pennyworth/exceptions.rb +0 -12
  15. data/lib/pennyworth/local_command_runner.rb +0 -2
  16. data/lib/pennyworth/matchers.rb +148 -0
  17. data/lib/pennyworth/remote_command_runner.rb +1 -2
  18. data/lib/pennyworth/runner.rb +1 -1
  19. data/lib/pennyworth/settings.rb +2 -2
  20. data/lib/pennyworth/spec.rb +1 -0
  21. data/lib/pennyworth/version.rb +1 -3
  22. data/lib/pennyworth/vm.rb +26 -1
  23. data/spec/build_base_command_spec.rb +18 -10
  24. data/spec/data/{kiwi → boxes}/definitions/base_opensuse12.3_kvm/config.sh +0 -0
  25. data/spec/data/{kiwi → boxes}/definitions/base_opensuse12.3_kvm/config.xml +0 -0
  26. data/spec/data/{kiwi → boxes}/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
  27. data/spec/data/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.sh +0 -0
  28. data/spec/data/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.xml +0 -0
  29. data/spec/data/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
  30. data/spec/data/{kiwi3/definitions/base_opensuse12.3_kvm/.gitkeep → boxes/definitions/veewee_definition/definition.rb} +0 -0
  31. data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse12.3_kvm/config.sh +0 -0
  32. data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse12.3_kvm/config.xml +0 -0
  33. data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
  34. data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse13.1_kvm/config.sh +0 -0
  35. data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse13.1_kvm/config.xml +0 -0
  36. data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
  37. data/spec/data/{kiwi3/definitions/base_opensuse13.1_kvm → boxes3/definitions/base_opensuse12.3_kvm}/.gitkeep +0 -0
  38. data/spec/data/{kiwi4/definitions/base_opensuse12.3_kvm → boxes3/definitions/base_opensuse13.1_kvm}/.gitkeep +0 -0
  39. data/spec/data/{kiwi4/definitions/base_opensuse13.1_kvm → boxes4/definitions/base_opensuse12.3_kvm}/.gitkeep +0 -0
  40. data/spec/data/boxes4/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  41. data/spec/import_base_command_spec.rb +15 -15
  42. data/spec/matchers_spec.rb +175 -0
  43. data/spec/remote_command_runner_spec.rb +5 -15
  44. data/spec/setup_command_spec.rb +63 -1
  45. metadata +33 -29
@@ -39,8 +39,6 @@ module Pennyworth
39
39
  "bash", "-c", *args, options
40
40
  )
41
41
  end
42
- rescue Cheetah::ExecutionFailed => e
43
- raise ExecutionFailed.new(e)
44
42
  end
45
43
 
46
44
  # Copy a local file to the remote system.
@@ -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.
@@ -21,7 +21,7 @@ module Pennyworth
21
21
  attr_reader :command_runner
22
22
 
23
23
  def cleanup_directory(dir)
24
- command_runner.run("test -d #{dir} && rm -r #{dir}")
24
+ command_runner.run("test -d #{dir} && rm -r #{dir} || true")
25
25
  end
26
26
  end
27
27
  end
@@ -26,8 +26,8 @@ module Pennyworth
26
26
  @definitions_dir = File.expand_path("~/.pennyworth")
27
27
  end
28
28
 
29
- def kiwi_dir
30
- File.join(@definitions_dir, "/kiwi")
29
+ def boxes_dir
30
+ File.join(@definitions_dir, "/boxes")
31
31
  end
32
32
 
33
33
  def vagrant_dir
@@ -38,6 +38,7 @@ require_relative "remote_command_runner"
38
38
  require_relative "settings"
39
39
  require_relative "local_runner"
40
40
  require_relative "local_command_runner"
41
+ require_relative "matchers"
41
42
 
42
43
  module Pennyworth
43
44
  module SpecHelper
@@ -16,7 +16,5 @@
16
16
  # you may find current contact information at www.suse.com
17
17
 
18
18
  module Pennyworth
19
-
20
- VERSION = "0.1.0"
21
-
19
+ VERSION = "0.2.0"
22
20
  end
@@ -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
- command_runner.run(*args)
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/kiwi-vagrant-build-environment" }
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
- @kiwi_dir = File.join(test_data_dir, "kiwi")
45
- @cmd = Pennyworth::BuildBaseCommand.new(@kiwi_dir)
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(@kiwi_dir, "box_state.yaml")
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(@kiwi_dir, "box_state.yaml")
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
- @kiwi_dir = File.join(test_data_dir, "kiwi2")
114
- @cmd = Pennyworth::BuildBaseCommand.new(@kiwi_dir)
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
 
@@ -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
- "/kiwi5/import_state.yaml")), headers: {})
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
- @kiwi_dir = File.join(test_data_dir, "kiwi")
37
- @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir, "http://example.com/pennyworth/")
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", "#{@kiwi_dir}/base_opensuse12.3_kvm.box",
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(@kiwi_dir, "http://example.com/pennyworth/")
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(@kiwi_dir, "http://example.com/pennyworth")
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
- @kiwi_dir = File.join(test_data_dir, "kiwi2")
87
- @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir)
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(@kiwi_dir, "box_state.yaml")))
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(@kiwi_dir, "import_state.yaml")
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
- @kiwi_dir = File.join(test_data_dir, "kiwi3")
130
- @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir, "http://example.com/pennyworth/")
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(@kiwi_dir, "box_state.yaml")))
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
- @kiwi_dir = File.join(test_data_dir, "kiwi4")
170
- @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir)
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