minionizer 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ module Minionizer
4
+ class FolderCreationTest < MiniTest::Test
5
+ describe FolderCreation do
6
+ let(:session) { 'MockSession' }
7
+ let(:path) { '/foo/bar' }
8
+ let(:folder_creation) { FolderCreation.new(session, options) }
9
+
10
+ describe '#call' do
11
+
12
+ describe 'only path is provided' do
13
+ let(:options) {{ path: path }}
14
+
15
+ it 'sends the mkdir command' do
16
+ session.expects(:exec).with(%Q{mkdir --parents #{path}})
17
+ folder_creation.call
18
+ end
19
+
20
+ end
21
+
22
+ describe 'mode is provided' do
23
+ let(:mode) { '0700' }
24
+ let(:options) {{ path: path, mode: mode }}
25
+
26
+ it 'sets the folder permissions' do
27
+ session.expects(:exec).with(%Q{mkdir --parents #{path}})
28
+ session.expects(:exec).with(%Q{chmod #{mode} #{path}})
29
+ folder_creation.call
30
+ end
31
+ end
32
+
33
+ describe 'owner is provided' do
34
+ let(:ownername) { 'otherowner' }
35
+ let(:options) {{ path: path, owner: ownername }}
36
+
37
+ it 'sets the folder owner' do
38
+ session.expects(:exec).with(%Q{mkdir --parents #{path}})
39
+ session.expects(:exec).with(%Q{chown #{ownername} #{path}})
40
+ folder_creation.call
41
+ end
42
+ end
43
+
44
+ describe 'group is provided' do
45
+ let(:groupname) { 'othergroup' }
46
+ let(:options) {{ path: path, group: groupname }}
47
+
48
+ it 'sets the folder group' do
49
+ session.expects(:exec).with(%Q{mkdir --parents #{path}})
50
+ session.expects(:exec).with(%Q{chgrp #{groupname} #{path}})
51
+ folder_creation.call
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,46 @@
1
+ require 'test_helper'
2
+
3
+ module Minionizer
4
+ class PublicSshKeyInjectionTest < MiniTest::Test
5
+
6
+ describe PublicSshKeyInjection do
7
+
8
+ describe '#call' do
9
+ let(:temp_file_path) { '/tmp/foobar' }
10
+ let(:temp_file_pointer) { OpenStruct.new(path: temp_file_path) }
11
+ let(:file_injection) { 'MockFileInjection' }
12
+ let(:file_injection_creator) { 'MockFileInjectionCreator' }
13
+ let(:session) { 'MockSession' }
14
+ let(:username) { 'foouser' }
15
+ let(:key_injection_options) {{
16
+ target_username: username,
17
+ file_injection_creator: file_injection_creator
18
+ }}
19
+ let(:key_injection) { PublicSshKeyInjection.new(session, key_injection_options) }
20
+ let(:expected_file_injection_options) {[
21
+ session,
22
+ {
23
+ :source_path => temp_file_path,
24
+ :target_path => "~#{username}/.ssh/authorized_keys",
25
+ :owner => username,
26
+ :group => username
27
+ }
28
+ ]}
29
+
30
+ before do
31
+ temp_file_pointer.expects(:unlink)
32
+ Tempfile.expects(:new).yields(temp_file_pointer).returns(temp_file_pointer)
33
+ write_file('data/public_keys/foobar.pubkey', 'foobar')
34
+ temp_file_pointer.expects(:puts).with('foobar')
35
+ end
36
+
37
+ it 'injects the file' do
38
+ file_injection_creator.expects(:new).with(*expected_file_injection_options).returns(file_injection)
39
+ file_injection.expects(:call)
40
+
41
+ key_injection.call
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ module Minionizer
4
+ class TaskTemplateTest < MiniTest::Test
5
+ describe TaskTemplate do
6
+ let(:session) { 'MockSession' }
7
+ let(:template) { TaskTemplate.new(session, :foo => 'bar') }
8
+
9
+ describe '#method_missing' do
10
+
11
+ it 'catches messages that match options' do
12
+ assert_equal('bar', template.foo)
13
+ end
14
+
15
+ it 'forwards unrecognized messages to super' do
16
+ assert_raises(NoMethodError) do
17
+ template.foobar
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ describe '#respond_to?' do
24
+
25
+ it 'recognizes passed in options as respondable methods' do
26
+ assert(template.respond_to?(:foo))
27
+ end
28
+
29
+ it 'properly responds to unrecognized methods' do
30
+ refute(template.respond_to?(:foobar))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+
3
+ module Minionizer
4
+ class UserCreationTest < MiniTest::Test
5
+ describe UserCreation do
6
+ let(:session) { 'MockSession' }
7
+ let(:full_name) { 'Test User' }
8
+ let(:username) { 'testuser' }
9
+ let(:options) {{ name: full_name, username: username }}
10
+ let(:user_creation) { UserCreation.new(session, options) }
11
+
12
+ describe '#call' do
13
+
14
+ describe 'user does not already exist' do
15
+
16
+ before do
17
+ session.stubs(:exec).with(%Q{id #{username}}).raises(CommandExecution::CommandError.new)
18
+ end
19
+
20
+ it 'creates the user' do
21
+ session.expects(:exec).with(%Q{adduser --disabled-password --gecos '#{full_name}' #{username}})
22
+ user_creation.call
23
+ end
24
+
25
+ end
26
+
27
+ describe 'user already exists' do
28
+
29
+ before do
30
+ session.stubs(:exec).with(%Q{id #{username}}).returns(true)
31
+ end
32
+
33
+ it 'does not create the user' do
34
+ session.expects(:exec).with(%Q{adduser --disabled-password --gecos '#{full_name}' #{username}}).never
35
+ user_creation.call
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,85 @@
1
+ require 'test_helper'
2
+
3
+ module Minionizer
4
+ class CommandExecutionTest < MiniTest::Test
5
+
6
+ describe CommandExecution do
7
+ let(:command) { 'foo --bar' }
8
+ let(:connection) { 'MockConnection' }
9
+ let(:execution) { CommandExecution.new(connection, command) }
10
+
11
+ describe '#call' do
12
+ let(:channel) { 'MockChannel' }
13
+ let(:stdout_data) { 'stdout' }
14
+ let(:stderr_data) { 'stderr' }
15
+ let(:exit_code) { 0 }
16
+ let(:exit_signal) { 'exit_signal' }
17
+
18
+ before do
19
+ connection.stubs(:open_channel).yields(channel)
20
+ channel.stubs(:on_data).yields(nil, stdout_data)
21
+ channel.stubs(:on_extended_data).yields(nil, stderr_data)
22
+ channel.
23
+ stubs(:on_request).
24
+ with('exit-status').
25
+ yields(nil, OpenStruct.new(:read_long => exit_code))
26
+ channel.
27
+ stubs(:on_request).
28
+ with('exit-signal').
29
+ yields(nil, OpenStruct.new(:read_long => exit_signal))
30
+ connection.stubs(:loop)
31
+ end
32
+
33
+ describe 'command runs successfully' do
34
+
35
+ before do
36
+ channel.
37
+ expects(:exec).
38
+ with(command).
39
+ yields(channel, true)
40
+ end
41
+
42
+ it 'runs the command' do
43
+ execution.call
44
+ end
45
+
46
+ end
47
+
48
+ describe 'command fails to be invoked' do
49
+
50
+ before do
51
+ channel.
52
+ expects(:exec).
53
+ with(command).
54
+ yields(channel, false)
55
+ end
56
+
57
+ it 'raises InvocationError' do
58
+ assert_raises(CommandExecution::InvocationError) do
59
+ execution.call
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ describe 'command returns non-zero exit status' do
66
+ let(:exit_code) { 1 }
67
+
68
+ before do
69
+ channel.
70
+ expects(:exec).
71
+ with(command).
72
+ yields(channel, true)
73
+ end
74
+
75
+ it 'raises CommandError' do
76
+ assert_raises(CommandExecution::CommandError) do
77
+ execution.call
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
@@ -1,14 +1,16 @@
1
1
  require 'test_helper'
2
2
 
3
3
  module Minionizer
4
- class ConfigurationTest < MiniTest::Unit::TestCase
4
+ class ConfigurationTest < MiniTest::Test
5
5
 
6
6
  describe Configuration do
7
7
  let(:config) { Configuration.instance }
8
+
8
9
  let(:minions) {{ 'foo.bar.com' => { :ssh => { :username => 'foo', :password => 'bar' } } }}
9
10
 
10
11
  before do
11
- write_file('config/minions.yml', minions.to_yaml)
12
+ config.instance_variable_set('@minions', nil)
13
+ write_file('./config/minions.yml', minions.to_yaml)
12
14
  end
13
15
 
14
16
  it 'instantiates a configuration' do
@@ -1,14 +1,14 @@
1
1
  require 'test_helper'
2
2
 
3
3
  module Minionizer
4
- class MinionTest < MiniTest::Unit::TestCase
4
+ class MinionTest < MiniTest::Test
5
5
  describe Minion do
6
6
  let(:username) { 'foo' }
7
7
  let(:password) { 'bar' }
8
8
  let(:credentials) {{ 'username' => username, 'password' => password }}
9
9
  let(:config) { Configuration.instance }
10
10
  let(:fqdn) { 'foo.bar.com' }
11
- let(:session_constructor) { Struct.new(:fqdn, :credentials) }
11
+ let(:session_constructor) { quacks_like(Session) }
12
12
  let(:minion) { Minion.new(fqdn, config, session_constructor) }
13
13
  let(:roles) { %w(foo bar) }
14
14
  let (:minion_config) {{ fqdn => { 'roles' => roles , 'ssh' => credentials } }}
@@ -22,7 +22,7 @@ module Minionizer
22
22
  end
23
23
 
24
24
  describe '#session' do
25
- let(:session) { MiniTest::NamedMock.new('session') }
25
+ let(:session) { quacks_like_instance_of(Session) }
26
26
 
27
27
  it 'creates a session' do
28
28
  session_constructor.expects(:new).with(fqdn, credentials).returns(session)
@@ -1,28 +1,28 @@
1
1
  require 'test_helper'
2
2
 
3
3
  module Minionizer
4
- class MinionizationTest < MiniTest::Unit::TestCase
4
+ class MinionizationTest < MiniTest::Test
5
5
 
6
6
  describe Minionization do
7
7
  let(:fqdn) { 'foo.bar.com' }
8
8
  let(:config) { Configuration.instance }
9
9
  let(:role_name) { 'web_server' }
10
10
  let(:role_class) { get_dynamic_class(role_name) }
11
- let(:minion) { MiniTest::NamedMock.new('minion') }
11
+ let(:minion) { quacks_like_instance_of(Minion) }
12
12
  let(:minionization) { Minionization.new(arguments, config, minion_constructor) }
13
13
  let(:minion_roles) {{ fqdn => { 'roles' => [role_name] }}}
14
- let(:minion_constructor) { Struct.new(:fqdn, :config) }
15
- let(:session) { MiniTest::NamedMock.new('session') }
16
- let(:role) { MiniTest::NamedMock.new('role') }
14
+ let(:minion_constructor) { quacks_like(Minion) }
15
+ let(:session) { quacks_like_instance_of(Session) }
16
+ let(:role) { quacks_like_instance_of(RoleTemplate) }
17
17
 
18
18
  before do
19
19
  config.stubs(:minions).returns(minion_roles)
20
- minion.expect(:roles, [role_name])
20
+ minion.expects(:roles).returns([role_name])
21
+ minion.expects(:session).returns(session)
21
22
  minion_constructor.expects(:new).with(fqdn, config).returns(minion)
22
23
  role_class.expects(:new).with(session).returns(role)
23
- role.expect(:call, true)
24
+ role.expects(:call)
24
25
  minionization.expects(:require).with("/roles/#{role_name}.rb")
25
- minion.expect(:session, session)
26
26
  end
27
27
 
28
28
  describe 'calling with a valid minion name' do
@@ -1,10 +1,10 @@
1
1
  require 'test_helper'
2
2
 
3
3
  module Minionizer
4
- class RoleTemplateTest < MiniTest::Unit::TestCase
4
+ class RoleTemplateTest < MiniTest::Test
5
5
 
6
6
  describe RoleTemplate do
7
- let(:session) { 'MockSession' }
7
+ let(:session) { quacks_like_instance_of(Session) }
8
8
  let(:template) { RoleTemplate.new(session) }
9
9
 
10
10
  it 'initilizes' do
@@ -1,17 +1,18 @@
1
1
  require 'test_helper'
2
2
 
3
3
  module Minionizer
4
- class SessionTest < MiniTest::Unit::TestCase
4
+ class SessionTest < MiniTest::Test
5
5
 
6
6
  describe Session do
7
7
  let(:fqdn) { 'foo.bar.com' }
8
8
  let(:username) { 'foo' }
9
9
  let(:password) { 'bar' }
10
10
  let(:credentials) {{ 'username' => username, 'password' => password }}
11
- let(:connector) { MiniTest::NamedMock.new(:connector) }
12
- let(:channel) { MiniTest::NamedMock.new(:channel) }
13
- let(:connection) { 'MockConnection' }
14
- let(:session) { Session.new(fqdn, credentials, connector) }
11
+ let(:connector) { mock('connector') }
12
+ let(:command_executor) { mock('CommandExecution') }
13
+ let(:execution) { mock('execution') }
14
+ let(:connection) { mock('connection') }
15
+ let(:session) { Session.new(fqdn, credentials, connector, command_executor) }
15
16
  let(:start_args) { [fqdn, username, { password: password }]}
16
17
 
17
18
  it 'instantiates' do
@@ -22,33 +23,77 @@ module Minionizer
22
23
  let(:command) { 'foobar' }
23
24
 
24
25
  before do
25
- connector.expect(:start, connection, start_args)
26
+ connector.expects(:start).with(*start_args).returns(connection)
26
27
  end
27
28
 
28
- describe 'when a single command is passed' do
29
+ describe '#sudo' do
30
+
31
+ describe 'with block argument' do
32
+
33
+ it 'prepends sudo onto the command line' do
34
+ command_executor.
35
+ expects(:new).
36
+ with(connection, sudoized(command)).
37
+ returns(OpenStruct.new(:call => true))
38
+ session.sudo do
39
+ session.exec(command)
40
+ end
41
+ end
42
+ end
43
+
44
+ describe 'with single command passed directly' do
45
+
46
+ it 'prepends sudo onto the command line' do
47
+ command_executor.
48
+ expects(:new).
49
+ with(connection, sudoized(command)).
50
+ returns(OpenStruct.new(:call => true))
51
+ session.sudo(command)
52
+ end
53
+
54
+ end
29
55
 
30
- before do
31
- connection.expects(:exec).with(command).returns("#{command} pong")
32
- connection.expects(:loop).returns('fixme')
56
+ describe 'with multiple commands passed directly' do
57
+ let(:commands) { %w{foo bar} }
58
+
59
+ it 'prepends sudo onto each command line' do
60
+ commands.each do |command|
61
+ command_executor.
62
+ expects(:new).
63
+ with(connection, sudoized(command)).
64
+ returns(OpenStruct.new(:call => true))
65
+ end
66
+ session.sudo(*commands)
67
+ end
33
68
  end
34
69
 
35
- it 'returns a single result' do
36
- assert_kind_of(String, session.exec(command))
70
+ end
71
+
72
+ describe 'when a single command is passed' do
73
+
74
+ let(:exit_code) { 0 }
75
+
76
+ it 'passes the command to the executor' do
77
+ command_executor.
78
+ expects(:new).
79
+ with(connection, command).
80
+ returns(OpenStruct.new(:call => true))
81
+ session.exec(command)
37
82
  end
83
+
38
84
  end
39
85
 
40
86
  describe 'when multiple commands are passed' do
41
- let(:commands) { %w(foo bar) }
87
+ let(:commands) { %w{foo bar} }
42
88
 
43
- before do
89
+ it 'passes each command individually to the executor' do
44
90
  commands.each do |command|
45
- connection.expects(:exec).with(command).returns("#{command} pong")
91
+ command_executor.
92
+ expects(:new).
93
+ with(connection, command).
94
+ returns(OpenStruct.new(:call => true))
46
95
  end
47
- connection.expects(:loop).twice.returns('fixme')
48
- end
49
-
50
- it 'returns multiple results' do
51
- assert_kind_of(Array, session.exec(commands))
96
+ session.exec(*commands)
52
97
  end
53
98
  end
54
99