minionizer 0.0.1 → 0.1.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.
@@ -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