pennyworth-tool 0.0.1

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 (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.hound.yml +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +18 -0
  6. data/CONTRIBUTING.md +67 -0
  7. data/COPYING +674 -0
  8. data/Gemfile +28 -0
  9. data/README.md +339 -0
  10. data/Rakefile +33 -0
  11. data/bin/pennyworth +26 -0
  12. data/config/setup.yml +17 -0
  13. data/examples/README.md +23 -0
  14. data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.sh +87 -0
  15. data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.xml +64 -0
  16. data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/etc/sysconfig/network/ifcfg-eth0 +2 -0
  17. data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  18. data/examples/vagrant/Vagrantfile +14 -0
  19. data/files/99-libvirt.rules +2 -0
  20. data/files/image_test-template.xml +43 -0
  21. data/files/pool-default.xml +6 -0
  22. data/lib/image_runner.rb +89 -0
  23. data/lib/pennyworth.rb +65 -0
  24. data/lib/pennyworth/cli.rb +339 -0
  25. data/lib/pennyworth/cli_host_controller.rb +107 -0
  26. data/lib/pennyworth/commands/base_command.rb +96 -0
  27. data/lib/pennyworth/commands/boot_command.rb +29 -0
  28. data/lib/pennyworth/commands/build_base_command.rb +103 -0
  29. data/lib/pennyworth/commands/command.rb +43 -0
  30. data/lib/pennyworth/commands/down_command.rb +25 -0
  31. data/lib/pennyworth/commands/import_base_command.rb +112 -0
  32. data/lib/pennyworth/commands/import_ssh_keys_command.rb +27 -0
  33. data/lib/pennyworth/commands/list_command.rb +41 -0
  34. data/lib/pennyworth/commands/setup_command.rb +209 -0
  35. data/lib/pennyworth/commands/shutdown_command.rb +28 -0
  36. data/lib/pennyworth/commands/status_command.rb +26 -0
  37. data/lib/pennyworth/commands/up_command.rb +27 -0
  38. data/lib/pennyworth/exceptions.rb +39 -0
  39. data/lib/pennyworth/helper.rb +39 -0
  40. data/lib/pennyworth/host_config.rb +86 -0
  41. data/lib/pennyworth/host_runner.rb +133 -0
  42. data/lib/pennyworth/image_runner.rb +89 -0
  43. data/lib/pennyworth/libvirt.rb +93 -0
  44. data/lib/pennyworth/local_command_runner.rb +77 -0
  45. data/lib/pennyworth/local_runner.rb +34 -0
  46. data/lib/pennyworth/lock_service.rb +87 -0
  47. data/lib/pennyworth/remote_command_runner.rb +144 -0
  48. data/lib/pennyworth/runner.rb +27 -0
  49. data/lib/pennyworth/settings.rb +42 -0
  50. data/lib/pennyworth/spec.rb +96 -0
  51. data/lib/pennyworth/spec_profiler.rb +85 -0
  52. data/lib/pennyworth/ssh_keys_importer.rb +107 -0
  53. data/lib/pennyworth/urls.rb +28 -0
  54. data/lib/pennyworth/vagrant.rb +81 -0
  55. data/lib/pennyworth/vagrant_command.rb +120 -0
  56. data/lib/pennyworth/vagrant_runner.rb +44 -0
  57. data/lib/pennyworth/version.rb +22 -0
  58. data/lib/pennyworth/vm.rb +62 -0
  59. data/man/.gitignore +2 -0
  60. data/man/pennyworth.1.md +28 -0
  61. data/pennyworth.gemspec +57 -0
  62. data/prophet/Gemfile +3 -0
  63. data/prophet/prophet.rb +82 -0
  64. data/spec/base_command_spec.rb +30 -0
  65. data/spec/build_base_command_spec.rb +147 -0
  66. data/spec/cli_host_controller_spec.rb +113 -0
  67. data/spec/data/hosts.yaml +10 -0
  68. data/spec/data/kiwi/base_opensuse12.3_kvm.box +1 -0
  69. data/spec/data/kiwi/base_opensuse13.1_kvm.box +1 -0
  70. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.sh +1 -0
  71. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.xml +1 -0
  72. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  73. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.sh +1 -0
  74. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.xml +1 -0
  75. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  76. data/spec/data/kiwi2/box_state.yaml +14 -0
  77. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.sh +1 -0
  78. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.xml +1 -0
  79. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  80. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.sh +1 -0
  81. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.xml +1 -0
  82. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  83. data/spec/data/kiwi3/box_state.yaml +13 -0
  84. data/spec/data/kiwi3/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
  85. data/spec/data/kiwi3/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  86. data/spec/data/kiwi3/import_state.yaml +3 -0
  87. data/spec/data/kiwi4/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
  88. data/spec/data/kiwi4/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  89. data/spec/data/kiwi4/import_state.yaml +3 -0
  90. data/spec/data/kiwi5/import_state.yaml +3 -0
  91. data/spec/data/vagrant/.gitkeep +0 -0
  92. data/spec/host_config_spec.rb +197 -0
  93. data/spec/host_runner_spec.rb +112 -0
  94. data/spec/image_runner_spec.rb +62 -0
  95. data/spec/import_base_command_spec.rb +189 -0
  96. data/spec/local_command_runner_spec.rb +117 -0
  97. data/spec/local_runner_spec.rb +42 -0
  98. data/spec/lock_service_spec.rb +95 -0
  99. data/spec/remote_command_runner_spec.rb +115 -0
  100. data/spec/settings_spec.rb +26 -0
  101. data/spec/setup_command_spec.rb +49 -0
  102. data/spec/spec_helper.rb +50 -0
  103. data/spec/spec_profiler_spec.rb +63 -0
  104. data/spec/spec_spec.rb +99 -0
  105. data/spec/support/command_runner_examples.rb +29 -0
  106. data/spec/support/runner_examples.rb +34 -0
  107. data/spec/urls_spec.rb +46 -0
  108. data/spec/vagrant_command_spec.rb +51 -0
  109. data/spec/vagrant_runner_spec.rb +40 -0
  110. data/spec/vagrant_spec.rb +288 -0
  111. data/spec/vm_spec.rb +56 -0
  112. metadata +257 -0
@@ -0,0 +1,189 @@
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
+ require "spec_helper.rb"
19
+
20
+ describe Pennyworth::ImportBaseCommand do
21
+
22
+ before(:all) do
23
+ Pennyworth::Cli.settings = Pennyworth::Settings.new
24
+ Pennyworth::Cli.settings.definitions_dir = test_data_dir
25
+ end
26
+
27
+ before(:each) do
28
+ stub_request(:get, /example.com.*import_state.yaml/).
29
+ with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
30
+ to_return(status: 200, body: File.read(File.join(test_data_dir,
31
+ "/kiwi5/import_state.yaml")), headers: {})
32
+ end
33
+
34
+ context "without box state file" do
35
+ before(:each) do
36
+ @kiwi_dir = File.join(test_data_dir, "kiwi")
37
+ @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir, "http://example.com/pennyworth/")
38
+ allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
39
+ allow(@cmd).to receive(:log)
40
+ allow(@cmd).to receive(:write_import_state_file) # Don't write state
41
+ end
42
+
43
+ it "imports a local box" do
44
+ expect(@cmd).to receive(:base_image_clean).with("base_opensuse12.3_kvm")
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",
47
+ "--force")
48
+
49
+ @cmd.execute("base_opensuse12.3_kvm", :local => true)
50
+ end
51
+
52
+ it "imports a remote box" do
53
+ allow(@cmd).to receive(:fetch_remote_box_state_file)
54
+
55
+ expect(@cmd).to receive(:base_image_clean).with("base_opensuse13.1_kvm")
56
+ expect_any_instance_of(Pennyworth::Vagrant).to receive(:run).with("box", "add",
57
+ "base_opensuse13.1_kvm",
58
+ "http://example.com/pennyworth/base_opensuse13.1_kvm.box", "--force")
59
+
60
+ @cmd.execute("base_opensuse13.1_kvm")
61
+ end
62
+
63
+ context "url checks" do
64
+ before(:each) do
65
+ @box_state_get = stub_request(:get, /example.com\/pennyworth\/box_state.yaml/)
66
+ end
67
+
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/")
70
+ cmd.read_remote_box_state_file()
71
+
72
+ assert_requested(@box_state_get)
73
+ end
74
+
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")
77
+ cmd.read_remote_box_state_file()
78
+
79
+ assert_requested(@box_state_get)
80
+ end
81
+ end
82
+ end
83
+
84
+ context "with box state file" do
85
+ before(:each) do
86
+ @kiwi_dir = File.join(test_data_dir, "kiwi2")
87
+ @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir)
88
+ allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
89
+ allow(@cmd).to receive(:log)
90
+ allow(@cmd).to receive(:fetch_remote_box_state_file).and_return(
91
+ File.read(File.join(@kiwi_dir, "box_state.yaml")))
92
+ end
93
+
94
+ it "writes import state file" do
95
+ allow(@cmd).to receive(:base_image_clean)
96
+ allow(@cmd).to receive(:vagrant)
97
+ allow_any_instance_of(Pennyworth::Vagrant).to receive(:run)
98
+
99
+ import_state_file = File.join(@kiwi_dir, "import_state.yaml")
100
+
101
+ FileUtils.rm(import_state_file) if File.exist?(import_state_file)
102
+
103
+ @cmd.execute("base_opensuse13.1_kvm", :local => true)
104
+ @cmd.execute("base_opensuse12.3_kvm", :local => true)
105
+
106
+ expected_content = <<-EOT
107
+ ---
108
+ base_opensuse13.1_kvm: 115469c104dcc69455f321eb086ffb11
109
+ base_opensuse12.3_kvm: e4e743b5340686d8488dbce54b5644d8
110
+ EOT
111
+
112
+ expect(File.read(import_state_file)).to eq expected_content
113
+
114
+ FileUtils.rm(import_state_file) if File.exist?(import_state_file)
115
+ end
116
+
117
+ it "reads remote box state file" do
118
+ box_state = @cmd.read_remote_box_state_file
119
+
120
+ expect(box_state["base_opensuse12.3_kvm"]["sources"]["config.sh"]).to eq(
121
+ "c6640ba00ab345b7491b836d517a637b")
122
+ expect(box_state["base_opensuse13.1_kvm"]["target"]).to eq(
123
+ "115469c104dcc69455f321eb086ffb11")
124
+ end
125
+ end
126
+
127
+ context "with box and import state files" do
128
+ before(:each) do
129
+ @kiwi_dir = File.join(test_data_dir, "kiwi3")
130
+ @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir, "http://example.com/pennyworth/")
131
+ allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
132
+ allow(@cmd).to receive(:log)
133
+ allow(@cmd).to receive(:write_import_state_file) # Don't write state
134
+ allow(@cmd).to receive(:fetch_remote_box_state_file).and_return(
135
+ File.read(File.join(@kiwi_dir, "box_state.yaml")))
136
+ end
137
+
138
+ it "imports changed local box" do
139
+ expect(@cmd).to receive(:base_image_clean)
140
+ expect_any_instance_of(Pennyworth::Vagrant).to receive(:run)
141
+
142
+ @cmd.execute("base_opensuse12.3_kvm", :local => true)
143
+ end
144
+
145
+ it "doesn't import unchanged local box" do
146
+ expect(@cmd).to_not receive(:base_image_clean)
147
+ expect_any_instance_of(Pennyworth::Vagrant).to_not receive(:run)
148
+
149
+ @cmd.execute("base_opensuse13.1_kvm", :local => true)
150
+ end
151
+
152
+ it "imports changed remote box" do
153
+ expect(@cmd).to receive(:base_image_clean)
154
+ expect_any_instance_of(Pennyworth::Vagrant).to receive(:run)
155
+
156
+ @cmd.execute("base_opensuse13.2_kvm")
157
+ end
158
+
159
+ it "doesn't import unchanged remote box" do
160
+ expect(@cmd).to_not receive(:base_image_clean)
161
+ expect_any_instance_of(Pennyworth::Vagrant).to_not receive(:run)
162
+
163
+ @cmd.execute("base_opensuse13.1_kvm")
164
+ end
165
+ end
166
+
167
+ context "without box state, but with import state files" do
168
+ before(:each) do
169
+ @kiwi_dir = File.join(test_data_dir, "kiwi4")
170
+ @cmd = Pennyworth::ImportBaseCommand.new(@kiwi_dir)
171
+ allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
172
+ allow(@cmd).to receive(:log)
173
+ end
174
+
175
+ it "removes imported state after import" do
176
+ expect(@cmd).to receive(:base_image_clean)
177
+ expect_any_instance_of(Pennyworth::Vagrant).to receive(:run)
178
+
179
+ import_state = @cmd.read_import_state_file
180
+ expect(import_state["base_opensuse13.1_kvm"]).to eq "115469c104dcc69455f321eb086ffb11"
181
+
182
+ expect(@cmd).to receive(:write_import_state_file).with(
183
+ {"base_opensuse13.1_kvm"=>nil, "base_opensuse12.3_kvm"=>"old_hash"}
184
+ )
185
+
186
+ @cmd.execute("base_opensuse13.1_kvm", :local => true)
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,117 @@
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
+ require "spec_helper"
19
+
20
+ include GivenFilesystemSpecHelpers
21
+
22
+ describe Pennyworth::LocalCommandRunner do
23
+ use_given_filesystem
24
+ let(:command_runner) { Pennyworth::LocalCommandRunner.new }
25
+
26
+ it_behaves_like "a command runner"
27
+
28
+ describe "#run" do
29
+ it "executes commands via Cheetah" do
30
+ expect(Cheetah).to receive(:run).with("bash", "-c", "foo bar", stdout: :capture)
31
+
32
+ command_runner.run("foo bar", stdout: :capture)
33
+ end
34
+
35
+ it "prepends the env variable to the command" do
36
+ runner = Pennyworth::LocalCommandRunner.new(
37
+ env: {
38
+ "MACHINERY_DIR" => "/tmp"
39
+ }
40
+ )
41
+ expect(runner).to receive(:with_env).with("MACHINERY_DIR" => "/tmp").and_call_original
42
+ expect(Cheetah).to receive(:run).with("bash", "-c", "foo bar", stdout: :capture)
43
+
44
+ runner.run("foo bar", stdout: :capture)
45
+ end
46
+ end
47
+
48
+ describe "#extract_file" do
49
+ before(:each) do
50
+ @source_file = given_dummy_file "example.file"
51
+ @target = given_directory
52
+ @expected_file = File.join(@target, "example.file")
53
+ end
54
+
55
+ it "extracts the file" do
56
+ command_runner.extract_file(@source_file, @target)
57
+
58
+ expect(File.exists?(File.join(@target, "example.file"))).to be(true)
59
+ end
60
+ end
61
+
62
+ describe "#inject_file" do
63
+ before(:each) do
64
+ @source_file = given_dummy_file "example.file"
65
+ @target = given_directory
66
+ @expected_file = File.join(@target, "example.file")
67
+ end
68
+
69
+ it "injects the file" do
70
+ command_runner.inject_file(@source_file, @target)
71
+ expect(File.exists?(File.join(@target, "example.file"))).to be(true)
72
+ end
73
+
74
+ it "copies the file and sets the owner" do
75
+ expect(FileUtils).to receive(:chown).with("tux", nil, @expected_file)
76
+
77
+ command_runner.inject_file(@source_file, @target, owner: "tux")
78
+ end
79
+
80
+ it "copies the file and sets the group" do
81
+ expect(FileUtils).to receive(:chown).with(nil, "tux", @expected_file)
82
+
83
+ command_runner.inject_file(@source_file, @target, group: "tux")
84
+ end
85
+
86
+ it "copies the file and sets the mode" do
87
+ expect(FileUtils).to receive(:chmod).with("600", @expected_file)
88
+
89
+ command_runner.inject_file(@source_file, @target, mode: "600")
90
+ end
91
+ end
92
+
93
+ describe "#inject_directory" do
94
+ before(:each) do
95
+ @source_dir = given_directory do
96
+ @source_file = given_dummy_file "example.file"
97
+ end
98
+
99
+ @target = given_directory
100
+ @expected_dir = File.join(@target, File.basename(@source_dir))
101
+ @expected_file = File.join(@target, File.basename(@source_dir), "example.file")
102
+ end
103
+
104
+ it "injects the directory" do
105
+ command_runner.inject_directory(@source_dir, @target)
106
+
107
+ expect(Dir.exists?(@expected_dir)).to be(true)
108
+ expect(File.exists?(@expected_file)).to be(true)
109
+ end
110
+
111
+ it "copies the directory and sets the user and group" do
112
+ expect(FileUtils).to receive(:chown_R).with("user", "group", @target)
113
+
114
+ command_runner.inject_directory(@source_dir, @target, owner: "user", group: "group")
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,42 @@
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
+ require "spec_helper"
19
+
20
+ describe Pennyworth::LocalRunner do
21
+ let(:runner) {
22
+ Pennyworth::LocalRunner.new
23
+ }
24
+
25
+ it_behaves_like "a runner"
26
+
27
+ describe "#command_runner" do
28
+ it "returns a LocalCommandRunner" do
29
+ expect(runner.command_runner).to be_a(Pennyworth::LocalCommandRunner)
30
+ end
31
+
32
+ it "forwards the :env and :command_map options to the LocalCommandRunner" do
33
+ opts = {
34
+ env: { "FOO" => "BAR" },
35
+ command_map: { "foo" => "/bar" }
36
+ }
37
+ expect(Pennyworth::LocalCommandRunner).to receive(:new).with(opts)
38
+
39
+ Pennyworth::LocalRunner.new(opts).command_runner
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,95 @@
1
+ # Copyright (c) 2015 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
+ require "spec_helper"
19
+
20
+ describe Pennyworth::LockService do
21
+ let(:lock_service) { Pennyworth::LockService.new("lock.example.com:9999") }
22
+
23
+ it "creates lock object" do
24
+ expect(lock_service.lock_server_host).to eq("lock.example.com")
25
+ expect(lock_service.lock_server_port).to eq("9999")
26
+ end
27
+
28
+ it "acquires lock" do
29
+ socket = double
30
+ expect(TCPSocket).to receive(:new).and_return(socket)
31
+ expect(socket).to receive(:puts).with("g my_test")
32
+ expect(socket).to receive(:gets).
33
+ and_return("1 Lock Get Success: my_test")
34
+
35
+ expect(lock_service.request_lock("my_test")).to be(true)
36
+ end
37
+
38
+ it "fails to acquire lock" do
39
+ socket = double
40
+ expect(TCPSocket).to receive(:new).and_return(socket)
41
+ expect(socket).to receive(:puts).with("g my_test")
42
+ expect(socket).to receive(:gets).
43
+ and_return("0 Lock Get Failure: my_test")
44
+
45
+ expect(lock_service.request_lock("my_test")).to be(false)
46
+ end
47
+
48
+ it "fails to release non-existing lock" do
49
+ expect {
50
+ lock_service.release_lock("inexisting lock")
51
+ }.to raise_error(Pennyworth::LockError)
52
+ end
53
+
54
+ it "releases lock" do
55
+ socket = double
56
+ expect(TCPSocket).to receive(:new).and_return(socket)
57
+ expect(socket).to receive(:puts).with("g my_test")
58
+ expect(socket).to receive(:gets).
59
+ and_return("1 Lock Get Success: my_test")
60
+
61
+ expect(lock_service.request_lock("my_test")).to be(true)
62
+
63
+ expect(socket).to receive(:close)
64
+
65
+ lock_service.release_lock("my_test")
66
+ end
67
+
68
+ it "returns locked status" do
69
+ socket = double
70
+ expect(TCPSocket).to receive(:new).and_return(socket)
71
+
72
+ expect(socket).to receive(:puts).with("i my_test")
73
+ expect(socket).to receive(:gets).
74
+ and_return("1 Lock Is Locked: my_test")
75
+
76
+ expect(socket).to receive(:puts).with("d my_test")
77
+ expect(socket).to receive(:gets).
78
+ and_return("my_test: 172.16.254.1:49716")
79
+
80
+ expect(lock_service.info("my_test")).
81
+ to eq "'my_test' is locked by 172.16.254.1"
82
+ end
83
+
84
+ it "returns unlocked status" do
85
+ socket = double
86
+ expect(TCPSocket).to receive(:new).and_return(socket)
87
+
88
+ expect(socket).to receive(:puts).with("i my_test")
89
+ expect(socket).to receive(:gets).
90
+ and_return("0 Lock Not Locked: my_test")
91
+
92
+ expect(lock_service.info("my_test")).
93
+ to eq "'my_test' is not locked"
94
+ end
95
+ end
@@ -0,0 +1,115 @@
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
+ require "spec_helper"
19
+
20
+ describe Pennyworth::RemoteCommandRunner do
21
+ let(:ssh_output) { "-rw-r--r-- 1 root root 642 Sep 27 22:06 /etc/hosts" }
22
+ let(:command_runner) { Pennyworth::RemoteCommandRunner.new("1.2.3.4", "root") }
23
+
24
+ it_behaves_like "a command runner"
25
+
26
+ describe "#run" do
27
+ it "calls ssh and returns the command's standard output" do
28
+ expect(Cheetah).to receive(:run).
29
+ and_return(ssh_output)
30
+
31
+ output = command_runner.run("ls", "-l", "/etc/hosts", stdout: :capture)
32
+
33
+ expect(output).to eq (ssh_output)
34
+ end
35
+
36
+ it "executes commands as given user" do
37
+ expect(Cheetah).to receive(:run).
38
+ with(
39
+ "ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no",
40
+ "root@1.2.3.4", "LC_ALL=C", "su", "-l", "vagrant", "-c", "ls", "-l", "/etc/hosts",
41
+ stdout: :capture).
42
+ and_return(ssh_output)
43
+
44
+ output = command_runner.run("ls", "-l", "/etc/hosts", as: "vagrant", stdout: :capture)
45
+
46
+ expect(output).to eq (ssh_output)
47
+ end
48
+
49
+ it "raises ExecutionFailed in case of errors" do
50
+ expect(Cheetah).to receive(:run).and_raise(Cheetah::ExecutionFailed.new(nil, nil, nil, nil))
51
+
52
+ expect {
53
+ command_runner.run("foo")
54
+ }.to raise_error(Pennyworth::ExecutionFailed)
55
+ end
56
+ end
57
+
58
+ describe "#extract_file" do
59
+ it "calls scp with source and destination as arguments" do
60
+ expect(Cheetah).to receive(:run)
61
+
62
+ command_runner.extract_file("/etc/hosts", "/tmp")
63
+ end
64
+ end
65
+
66
+ describe "#inject_file" do
67
+ it "calls scp with source and destination as arguments" do
68
+ expect(Cheetah).to receive(:run)
69
+
70
+ command_runner.inject_file("/tmp/hosts", "/etc")
71
+ end
72
+
73
+ it "copies the file and sets the owner" do
74
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/scp/) }
75
+ expect(Cheetah).to receive(:run) { |*args| expect(args.join(" ")).to match(/chown.*tux/) }
76
+
77
+ command_runner.inject_file("/tmp/hosts", "/etc", owner: "tux")
78
+ end
79
+
80
+ it "copies the file and sets the group" do
81
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/scp/) }
82
+ expect(Cheetah).to receive(:run) { |*args| expect(args.join(" ")).to match(/chown.*:tux/) }
83
+
84
+ command_runner.inject_file("/tmp/hosts", "/etc", group: "tux")
85
+ end
86
+
87
+ it "copies the file and sets the mode" do
88
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/scp/) }
89
+ expect(command_runner).to receive(:run) do |*args|
90
+ expect(args.join(" ")).to include("chmod 600")
91
+ end
92
+
93
+ command_runner.inject_file("/tmp/hosts", "/etc", mode: "600")
94
+ end
95
+ end
96
+
97
+ describe "#inject_directory" do
98
+ it "calls scp with source and destination as arguments" do
99
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/mkdir -p/) }
100
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/scp/) }
101
+
102
+ command_runner.inject_directory("/tmp/hosts", "/etc")
103
+ end
104
+
105
+ it "copies the directory and sets the user and group" do
106
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/mkdir -p/) }
107
+ expect(Cheetah).to receive(:run) { |*args| expect(args).to include(/scp/) }
108
+ expect(Cheetah).to receive(:run) do |*args|
109
+ expect(args.join(" ")).to include("chown -R user:group")
110
+ end
111
+
112
+ command_runner.inject_directory("/tmp/hosts", "/etc", owner: "user", group: "group")
113
+ end
114
+ end
115
+ end