pennyworth-tool 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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