minionizer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Gemfile.lock +29 -19
- data/README.md +13 -10
- data/Rakefile +2 -0
- data/bin/minionize +11 -1
- data/lib/core/file_injection.rb +31 -3
- data/lib/core/public_ssh_key_injection.rb +29 -8
- data/lib/core/task_template.rb +3 -0
- data/lib/minionizer/command_execution.rb +17 -4
- data/lib/minionizer/cryptographer.rb +84 -0
- data/lib/minionizer/initialization.rb +55 -0
- data/lib/minionizer/session.rb +28 -11
- data/lib/minionizer/version.rb +1 -1
- data/lib/minionizer.rb +2 -0
- data/minionizer.gemspec +3 -0
- data/test/integration/core_library_test.rb +9 -4
- data/test/test_helper.rb +0 -1
- data/test/unit/lib/core/file_injection_test.rb +66 -29
- data/test/unit/lib/core/public_ssh_key_injection_test.rb +22 -11
- data/test/unit/lib/core/task_template_test.rb +9 -1
- data/test/unit/lib/minionizer/cryptographer_test.rb +145 -0
- data/test/unit/lib/minionizer/initialization_test.rb +113 -0
- data/test/unit/lib/minionizer/session_test.rb +51 -9
- metadata +50 -2
@@ -5,58 +5,95 @@ module Minionizer
|
|
5
5
|
|
6
6
|
describe FileInjection do
|
7
7
|
let(:session) { 'MockSession' }
|
8
|
-
let(:source_path) { 'data/source_file.txt'}
|
9
8
|
let(:target_path) { '/var/target_file.txt'}
|
10
|
-
let(:
|
9
|
+
let(:string_io_creator) { mock('StringIO') }
|
10
|
+
let(:injection) { FileInjection.new(session, options.merge(string_io_creator: string_io_creator)) }
|
11
11
|
|
12
12
|
describe '#call' do
|
13
13
|
let(:source_contents) { 'Source Contents' }
|
14
|
+
let(:string_io) { mock('StringIO') }
|
14
15
|
|
15
16
|
before do
|
16
|
-
write_file(source_path, source_contents)
|
17
17
|
session.expects(:exec).with(%Q{mkdir --parents #{File.dirname(target_path)}})
|
18
|
-
session.expects(:
|
18
|
+
session.expects(:scp).with(string_io, target_path)
|
19
19
|
end
|
20
20
|
|
21
|
-
describe '
|
22
|
-
let(:options) {{
|
21
|
+
describe 'provides raw contents instead of source file' do
|
22
|
+
let(:options) {{ contents: source_contents, target_path: target_path }}
|
23
23
|
|
24
|
-
it '
|
24
|
+
it 'writes the contents to the file' do
|
25
|
+
string_io_creator.expects(:new).with(source_contents).returns(string_io)
|
25
26
|
injection.call
|
26
27
|
end
|
27
|
-
|
28
28
|
end
|
29
29
|
|
30
|
-
describe '
|
31
|
-
let(:mode) { '0700' }
|
32
|
-
let(:options) {{ source_path: source_path, target_path: target_path, mode: mode }}
|
30
|
+
describe 'source file is provided' do
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
injection.call
|
32
|
+
before do
|
33
|
+
write_file(source_path, source_contents)
|
37
34
|
end
|
38
|
-
end
|
39
35
|
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
describe 'source is plain text file' do
|
37
|
+
let(:source_path) { 'data/source_file.txt'}
|
38
|
+
let(:options) {{ source_path: source_path, target_path: target_path }}
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
40
|
+
before do
|
41
|
+
string_io_creator.expects(:new).with(source_contents).returns(string_io)
|
42
|
+
end
|
49
43
|
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
it 'sends a command to session' do
|
45
|
+
injection.call
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'mode is provided' do
|
49
|
+
let(:mode) { '0700' }
|
50
|
+
let(:options) {{ source_path: source_path, target_path: target_path, mode: mode }}
|
51
|
+
|
52
|
+
it 'sets the file permissions' do
|
53
|
+
session.expects(:exec).with(%Q{chmod #{mode} #{target_path}})
|
54
|
+
injection.call
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'owner is provided' do
|
59
|
+
let(:ownername) { 'otheruser' }
|
60
|
+
let(:options) {{ source_path: source_path, target_path: target_path, owner: ownername }}
|
61
|
+
|
62
|
+
it 'sets the file owner' do
|
63
|
+
session.expects(:exec).with(%Q{chown #{ownername} #{target_path}})
|
64
|
+
injection.call
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'group is provided' do
|
69
|
+
let(:groupname) { 'othergroup' }
|
70
|
+
let(:options) {{ source_path: source_path, target_path: target_path, group: groupname }}
|
71
|
+
|
72
|
+
it 'sets the file group' do
|
73
|
+
session.expects(:exec).with(%Q{chgrp #{groupname} #{target_path}})
|
74
|
+
injection.call
|
75
|
+
end
|
76
|
+
end
|
53
77
|
|
54
|
-
it 'sets the file group' do
|
55
|
-
session.expects(:exec).with(%Q{chgrp #{groupname} #{target_path}})
|
56
|
-
injection.call
|
57
78
|
end
|
79
|
+
|
80
|
+
describe 'source is erb file' do
|
81
|
+
let(:source_path) { 'data/source_file.erb'}
|
82
|
+
let(:injectable_contents) { 'Successfully Injected Contents' }
|
83
|
+
let(:contents_template) { 'Source Contents with ERB: ERB_HERE' }
|
84
|
+
let(:source_contents) { contents_template.gsub('ERB_HERE', '<%= injectable_contents %>') }
|
85
|
+
let(:expected_contents) { contents_template.gsub('ERB_HERE', injectable_contents) }
|
86
|
+
let(:options) {{ source_path: source_path, target_path: target_path }}
|
87
|
+
|
88
|
+
it 'processes the erb' do
|
89
|
+
string_io_creator.expects(:new).with(expected_contents).returns(string_io)
|
90
|
+
injection.call
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
58
94
|
end
|
59
95
|
|
96
|
+
|
60
97
|
end
|
61
98
|
|
62
99
|
end
|
@@ -6,35 +6,46 @@ module Minionizer
|
|
6
6
|
describe PublicSshKeyInjection do
|
7
7
|
|
8
8
|
describe '#call' do
|
9
|
-
let(:
|
10
|
-
let(:
|
11
|
-
let(:
|
12
|
-
let(:file_injection_creator) { '
|
9
|
+
let(:key) { 'foobar' }
|
10
|
+
let(:file_injection) { mock('file_injecton') }
|
11
|
+
let(:folder_creation) { mock('folder_creation') }
|
12
|
+
let(:file_injection_creator) { mock('FileInjection') }
|
13
|
+
let(:folder_creation_creator) { mock('FolderCreation') }
|
13
14
|
let(:session) { 'MockSession' }
|
14
15
|
let(:username) { 'foouser' }
|
15
16
|
let(:key_injection_options) {{
|
16
17
|
target_username: username,
|
17
|
-
file_injection_creator: file_injection_creator
|
18
|
+
file_injection_creator: file_injection_creator,
|
19
|
+
folder_creation_creator: folder_creation_creator
|
18
20
|
}}
|
19
21
|
let(:key_injection) { PublicSshKeyInjection.new(session, key_injection_options) }
|
22
|
+
let(:expected_folder_creation_options) {[
|
23
|
+
session,
|
24
|
+
{
|
25
|
+
:path => "/home/#{username}/.ssh",
|
26
|
+
:owner => username,
|
27
|
+
:group => username,
|
28
|
+
mode: 700
|
29
|
+
}
|
30
|
+
]}
|
20
31
|
let(:expected_file_injection_options) {[
|
21
32
|
session,
|
22
33
|
{
|
23
|
-
:
|
24
|
-
:target_path => "
|
34
|
+
:contents => key,
|
35
|
+
:target_path => "/home/#{username}/.ssh/authorized_keys",
|
25
36
|
:owner => username,
|
26
|
-
:group => username
|
37
|
+
:group => username,
|
38
|
+
mode: 600
|
27
39
|
}
|
28
40
|
]}
|
29
41
|
|
30
42
|
before do
|
31
|
-
temp_file_pointer.expects(:unlink)
|
32
|
-
Tempfile.expects(:new).yields(temp_file_pointer).returns(temp_file_pointer)
|
33
43
|
write_file('data/public_keys/foobar.pubkey', 'foobar')
|
34
|
-
temp_file_pointer.expects(:puts).with('foobar')
|
35
44
|
end
|
36
45
|
|
37
46
|
it 'injects the file' do
|
47
|
+
folder_creation_creator.expects(:new).with(*expected_folder_creation_options).returns(folder_creation)
|
48
|
+
folder_creation.expects(:call)
|
38
49
|
file_injection_creator.expects(:new).with(*expected_file_injection_options).returns(file_injection)
|
39
50
|
file_injection.expects(:call)
|
40
51
|
|
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
module Minionizer
|
4
4
|
class TaskTemplateTest < MiniTest::Test
|
5
5
|
describe TaskTemplate do
|
6
|
-
let(:session) {
|
6
|
+
let(:session) { Minitest::Mock.new }
|
7
7
|
let(:template) { TaskTemplate.new(session, :foo => 'bar') }
|
8
8
|
|
9
9
|
describe '#method_missing' do
|
@@ -30,6 +30,14 @@ module Minionizer
|
|
30
30
|
refute(template.respond_to?(:foobar))
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
describe '#download_file' do
|
35
|
+
it 'downloads a file' do
|
36
|
+
session.expect(:exec, true, [/wget/])
|
37
|
+
template.download_file('source','destination')
|
38
|
+
session.verify
|
39
|
+
end
|
40
|
+
end
|
33
41
|
end
|
34
42
|
end
|
35
43
|
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Minionizer
|
4
|
+
class CryptographerTest < MiniTest::Test
|
5
|
+
describe Cryptographer do
|
6
|
+
let(:cryptographer) { Cryptographer.new }
|
7
|
+
let(:unencrypted_filename) { 'foobar.txt' }
|
8
|
+
let(:encrypted_filename) { "#{unencrypted_filename}.enc" }
|
9
|
+
let(:path_to_unencrypted_filename) { "#{Cryptographer::SECRET_FOLDER}/#{unencrypted_filename}" }
|
10
|
+
let(:path_to_encrypted_filename) { "#{Cryptographer::SAFE_FOLDER}/#{encrypted_filename}" }
|
11
|
+
let(:path_to_stored_sha) { "#{Cryptographer::SAFE_FOLDER}/#{unencrypted_filename}.sha" }
|
12
|
+
|
13
|
+
before do
|
14
|
+
Dir.stubs(:foreach).with(Cryptographer::SECRET_FOLDER).yields(unencrypted_filename)
|
15
|
+
Dir.stubs(:foreach).with(Cryptographer::SAFE_FOLDER).yields(encrypted_filename)
|
16
|
+
@stdout = $stdout
|
17
|
+
$stdout = StringIO.new
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
$stdout = @stdout
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#generate_key' do
|
25
|
+
|
26
|
+
it 'generates a key' do
|
27
|
+
cryptographer.expects(:system).with() { |c| c.match(/--gen-key/) }
|
28
|
+
cryptographer.generate_key
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#encrypt_secrets' do
|
34
|
+
|
35
|
+
describe 'when remote sha does not exist' do
|
36
|
+
|
37
|
+
before do
|
38
|
+
File.expects(:exists?).with(path_to_stored_sha).returns(false)
|
39
|
+
cryptographer.stubs(:`).with() { |c| c.match(/--fingerprint/) }.
|
40
|
+
returns("fingerprint\n")
|
41
|
+
cryptographer.stubs(:system).with() { |c| c.match(/sha512sum/) }
|
42
|
+
cryptographer.stubs(:system).with() do |c|
|
43
|
+
c.match(/--encrypt #{path_to_unencrypted_filename}/)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'encrypts the file' do
|
48
|
+
cryptographer.expects(:system).with() do |c|
|
49
|
+
c.match(/--encrypt #{path_to_unencrypted_filename}/)
|
50
|
+
end
|
51
|
+
cryptographer.encrypt_secrets
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'generates the stored sha file' do
|
55
|
+
cryptographer.expects(:system).
|
56
|
+
with("sha512sum #{path_to_unencrypted_filename} > #{path_to_stored_sha}")
|
57
|
+
cryptographer.encrypt_secrets
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'when remote sha exists' do
|
63
|
+
|
64
|
+
before do
|
65
|
+
File.expects(:exists?).with(path_to_stored_sha).returns(true)
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'when shas match' do
|
69
|
+
before do
|
70
|
+
cryptographer.stubs(:`).with("sha512sum #{path_to_unencrypted_filename}").returns('SAMEY')
|
71
|
+
cryptographer.stubs(:`).with("cat #{path_to_stored_sha}").returns('SAMEY')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'does not encrypt the file' do
|
75
|
+
cryptographer.expects(:system).with() { |c| c.match(/--encrypt/) }.never
|
76
|
+
cryptographer.encrypt_secrets
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'when shas do not match' do
|
82
|
+
before do
|
83
|
+
cryptographer.stubs(:system).with() { |c| c.match(/sha512sum/) }
|
84
|
+
cryptographer.stubs(:`).with("sha512sum #{path_to_unencrypted_filename}").
|
85
|
+
returns('SAMEY')
|
86
|
+
cryptographer.stubs(:`).with("cat #{path_to_stored_sha}").returns('NOTSAMEY')
|
87
|
+
cryptographer.stubs(:`).with() { |c| c.match(/--fingerprint/) }.
|
88
|
+
returns("fingerprint\n")
|
89
|
+
cryptographer.stubs(:system).with() { |c| c.match(/--encrypt/) }
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'encrypts the file' do
|
93
|
+
cryptographer.expects(:system).with() do |c|
|
94
|
+
c.match(/--encrypt #{path_to_unencrypted_filename}/)
|
95
|
+
end
|
96
|
+
cryptographer.encrypt_secrets
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'generates the stored sha file' do
|
100
|
+
cryptographer.expects(:system).
|
101
|
+
with("sha512sum #{path_to_unencrypted_filename} > #{path_to_stored_sha}")
|
102
|
+
cryptographer.encrypt_secrets
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#decrypt_secrets' do
|
110
|
+
describe 'when shas match' do
|
111
|
+
|
112
|
+
before do
|
113
|
+
File.expects(:exists?).with(path_to_stored_sha).returns(true)
|
114
|
+
cryptographer.stubs(:`).with("sha512sum #{path_to_unencrypted_filename}").
|
115
|
+
returns('SAMEY')
|
116
|
+
cryptographer.stubs(:`).with("cat #{path_to_stored_sha}").returns('SAMEY')
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'does not excrypt the file' do
|
120
|
+
cryptographer.expects(:system).with() { |c| c.match(/--decrypt/) }.never
|
121
|
+
cryptographer.decrypt_secrets
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'when shas do not match' do
|
126
|
+
|
127
|
+
before do
|
128
|
+
cryptographer.stubs(:`).with("sha512sum #{path_to_unencrypted_filename}").
|
129
|
+
returns('SAMEY')
|
130
|
+
cryptographer.stubs(:`).with("cat #{path_to_stored_sha}").returns('NOTSAMEY')
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'decrypts the file' do
|
134
|
+
cryptographer.expects(:system).with() do |c|
|
135
|
+
c.match(/--decrypt #{path_to_encrypted_filename}/)
|
136
|
+
end
|
137
|
+
cryptographer.decrypt_secrets
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Minionizer
|
4
|
+
class InitializationTest < MiniTest::Test
|
5
|
+
|
6
|
+
describe Initialization do
|
7
|
+
let(:path) { '/some/path' }
|
8
|
+
let(:initialization) { Initialization.new(path) }
|
9
|
+
|
10
|
+
describe '.create' do
|
11
|
+
it 'initializes and saves' do
|
12
|
+
Initialization.any_instance.expects(:save)
|
13
|
+
Initialization.create('/some/path')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#save' do
|
18
|
+
|
19
|
+
before do
|
20
|
+
File.stubs(:readlines).with("#{path}/.gitignore").returns(['data/secrets'])
|
21
|
+
initialization.stubs(:system)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'directory structure' do
|
25
|
+
|
26
|
+
before do
|
27
|
+
File.stubs(:readlines).with("#{path}/.gitignore").returns([])
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:folders) {[
|
31
|
+
'', #root folder
|
32
|
+
'/config',
|
33
|
+
'/data/encrypted_secrets',
|
34
|
+
'/data/public_keys',
|
35
|
+
'/data/secrets',
|
36
|
+
'/lib',
|
37
|
+
'/roles'
|
38
|
+
]}
|
39
|
+
|
40
|
+
it 'creates it quietly' do
|
41
|
+
folders.each do |folder|
|
42
|
+
initialization.expects(:system).with("mkdir -p #{path}#{folder}")
|
43
|
+
end
|
44
|
+
initialization.save
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'minions.yml' do
|
49
|
+
|
50
|
+
it 'touches the file' do
|
51
|
+
initialization.
|
52
|
+
expects(:system).
|
53
|
+
with("touch #{path}/config/minions.yml")
|
54
|
+
initialization.save
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'gitignore' do
|
59
|
+
|
60
|
+
before do
|
61
|
+
initialization.
|
62
|
+
stubs(:system).
|
63
|
+
with("touch #{path}/.gitignore")
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'touches the file' do
|
67
|
+
initialization.
|
68
|
+
expects(:system).
|
69
|
+
with("touch #{path}/.gitignore")
|
70
|
+
initialization.save
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'secrets line already added to file' do
|
74
|
+
|
75
|
+
it 'does not add it again' do
|
76
|
+
#################################################################
|
77
|
+
### Because obj.expects().with().never does not properly fail
|
78
|
+
### when the method is called with the given parameters.
|
79
|
+
### https://github.com/freerange/mocha/issues/82
|
80
|
+
### http://stackoverflow.com/q/17287665/811172
|
81
|
+
class NeverError < StandardError; end
|
82
|
+
initialization.
|
83
|
+
stubs(:system).
|
84
|
+
with("echo 'data/secrets' > #{path}/.gitignore").
|
85
|
+
raises(NeverError)
|
86
|
+
begin
|
87
|
+
initialization.save
|
88
|
+
rescue NeverError
|
89
|
+
assert false
|
90
|
+
end
|
91
|
+
#################################################################
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'secrets line is not in file' do
|
96
|
+
|
97
|
+
before do
|
98
|
+
File.stubs(:readlines).with("#{path}/.gitignore").returns(['foo/bar'])
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'adds it to the file' do
|
102
|
+
initialization.
|
103
|
+
expects(:system).
|
104
|
+
with("echo 'data/secrets' > #{path}/.gitignore")
|
105
|
+
initialization.save
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -8,22 +8,64 @@ module Minionizer
|
|
8
8
|
let(:username) { 'foo' }
|
9
9
|
let(:password) { 'bar' }
|
10
10
|
let(:credentials) {{ 'username' => username, 'password' => password }}
|
11
|
-
let(:
|
11
|
+
let(:ssh_connector) { mock('ssh_connector') }
|
12
|
+
let(:scp_connector) { mock('scp_connector') }
|
12
13
|
let(:command_executor) { mock('CommandExecution') }
|
13
14
|
let(:execution) { mock('execution') }
|
14
|
-
let(:
|
15
|
-
let(:
|
15
|
+
let(:ssh_connection) { mock('ssh_connection') }
|
16
|
+
let(:scp_connection) { mock('scp_connection') }
|
17
|
+
let(:session) { Session.new(fqdn, credentials, ssh_connector, scp_connector, command_executor) }
|
16
18
|
let(:start_args) { [fqdn, username, { password: password }]}
|
17
19
|
|
18
20
|
it 'instantiates' do
|
19
21
|
assert_kind_of(Session, session)
|
20
22
|
end
|
21
23
|
|
24
|
+
describe '#scp' do
|
25
|
+
let(:source_path) { '/source/path' }
|
26
|
+
let(:target_path) { '/target/path' }
|
27
|
+
|
28
|
+
before do
|
29
|
+
scp_connector.expects(:start).with(*start_args).returns(scp_connection)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'straight scp' do
|
33
|
+
|
34
|
+
it 'copies the file to the target location' do
|
35
|
+
scp_connection.expects(:upload!).with(source_path, target_path)
|
36
|
+
session.scp(source_path, target_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'within sudo block' do
|
42
|
+
let(:hex) { 'securehex' }
|
43
|
+
let(:temp_filename) { "#{hex}.minionizer_tempfile" }
|
44
|
+
|
45
|
+
before do
|
46
|
+
ssh_connector.expects(:start).with(*start_args).returns(ssh_connection)
|
47
|
+
SecureRandom.expects(:hex).returns(hex)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'copies the file to temp location and then moves it' do
|
51
|
+
scp_connection.expects(:upload!).with(source_path, temp_filename)
|
52
|
+
command_executor.
|
53
|
+
expects(:new).
|
54
|
+
with(ssh_connection, sudoized("mv #{temp_filename} #{target_path}"), {}).
|
55
|
+
returns(OpenStruct.new(:call => true))
|
56
|
+
session.sudo do |sudo_session|
|
57
|
+
sudo_session.scp(source_path, target_path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
22
64
|
describe 'running commands' do
|
23
65
|
let(:command) { 'foobar' }
|
24
66
|
|
25
67
|
before do
|
26
|
-
|
68
|
+
ssh_connector.expects(:start).with(*start_args).returns(ssh_connection)
|
27
69
|
end
|
28
70
|
|
29
71
|
describe '#sudo' do
|
@@ -33,7 +75,7 @@ module Minionizer
|
|
33
75
|
it 'prepends sudo onto the command line' do
|
34
76
|
command_executor.
|
35
77
|
expects(:new).
|
36
|
-
with(
|
78
|
+
with(ssh_connection, sudoized(command), {}).
|
37
79
|
returns(OpenStruct.new(:call => true))
|
38
80
|
session.sudo do
|
39
81
|
session.exec(command)
|
@@ -46,7 +88,7 @@ module Minionizer
|
|
46
88
|
it 'prepends sudo onto the command line' do
|
47
89
|
command_executor.
|
48
90
|
expects(:new).
|
49
|
-
with(
|
91
|
+
with(ssh_connection, sudoized(command), {}).
|
50
92
|
returns(OpenStruct.new(:call => true))
|
51
93
|
session.sudo(command)
|
52
94
|
end
|
@@ -60,7 +102,7 @@ module Minionizer
|
|
60
102
|
commands.each do |command|
|
61
103
|
command_executor.
|
62
104
|
expects(:new).
|
63
|
-
with(
|
105
|
+
with(ssh_connection, sudoized(command), {}).
|
64
106
|
returns(OpenStruct.new(:call => true))
|
65
107
|
end
|
66
108
|
session.sudo(*commands)
|
@@ -76,7 +118,7 @@ module Minionizer
|
|
76
118
|
it 'passes the command to the executor' do
|
77
119
|
command_executor.
|
78
120
|
expects(:new).
|
79
|
-
with(
|
121
|
+
with(ssh_connection, command, {}).
|
80
122
|
returns(OpenStruct.new(:call => true))
|
81
123
|
session.exec(command)
|
82
124
|
end
|
@@ -90,7 +132,7 @@ module Minionizer
|
|
90
132
|
commands.each do |command|
|
91
133
|
command_executor.
|
92
134
|
expects(:new).
|
93
|
-
with(
|
135
|
+
with(ssh_connection, command, {}).
|
94
136
|
returns(OpenStruct.new(:call => true))
|
95
137
|
end
|
96
138
|
session.exec(*commands)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minionizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan S. Garvin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: binding_of_caller
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.7'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: net-ssh
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,20 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '2.9'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: net-scp
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.2'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: fakefs
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +94,20 @@ dependencies:
|
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
96
|
version: '1.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.4'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5.4'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: rake
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,6 +147,8 @@ files:
|
|
105
147
|
- lib/minionizer.rb
|
106
148
|
- lib/minionizer/command_execution.rb
|
107
149
|
- lib/minionizer/configuration.rb
|
150
|
+
- lib/minionizer/cryptographer.rb
|
151
|
+
- lib/minionizer/initialization.rb
|
108
152
|
- lib/minionizer/minion.rb
|
109
153
|
- lib/minionizer/minionization.rb
|
110
154
|
- lib/minionizer/role_template.rb
|
@@ -122,6 +166,8 @@ files:
|
|
122
166
|
- test/unit/lib/core/user_creation_test.rb
|
123
167
|
- test/unit/lib/minionizer/command_execution_test.rb
|
124
168
|
- test/unit/lib/minionizer/configuration_test.rb
|
169
|
+
- test/unit/lib/minionizer/cryptographer_test.rb
|
170
|
+
- test/unit/lib/minionizer/initialization_test.rb
|
125
171
|
- test/unit/lib/minionizer/minion_test.rb
|
126
172
|
- test/unit/lib/minionizer/minionization_test.rb
|
127
173
|
- test/unit/lib/minionizer/role_template_test.rb
|
@@ -161,6 +207,8 @@ test_files:
|
|
161
207
|
- test/unit/lib/core/user_creation_test.rb
|
162
208
|
- test/unit/lib/minionizer/command_execution_test.rb
|
163
209
|
- test/unit/lib/minionizer/configuration_test.rb
|
210
|
+
- test/unit/lib/minionizer/cryptographer_test.rb
|
211
|
+
- test/unit/lib/minionizer/initialization_test.rb
|
164
212
|
- test/unit/lib/minionizer/minion_test.rb
|
165
213
|
- test/unit/lib/minionizer/minionization_test.rb
|
166
214
|
- test/unit/lib/minionizer/role_template_test.rb
|