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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82bef054c00cc362c8c6bde7b0557b1ec7ea8966
4
- data.tar.gz: 496df270bcb0c2c4fe65d3bb291ef5d9d9673e69
3
+ metadata.gz: f0f6f2ff87e40cfacb8163853951e4b6d2851dd3
4
+ data.tar.gz: aaa855643097d24799b62ed3b6f1fc187670a224
5
5
  SHA512:
6
- metadata.gz: b437e19e86a6bc97c546ba32193a77812c0710c50b375927ddd0c49b129fab0e96b4b91ab9e6456a409b10061e7ca04398220bb125c4a85a7c56382d06d67621
7
- data.tar.gz: ef1cc521975e07f8fbee54cd3e3f5415d0610f2dfb6bc6cb5a0f5b79725d05942f4c9f1baf8e915729ecb6a9d32a9bdf111c936f233f7c76dd9abf1797668588
6
+ metadata.gz: caf5ec31a1e30efac84dc898af40c4a7d9e2e247fcfdae6110d5bb93c9ab657f48348f664f5dc0dec5a40721c2181f85f4bc337e055e989ccf38abbcde596f70
7
+ data.tar.gz: 6a366d4b175747590bc289741068d20523b32716580ecae1244f4dd84aa2d91d4bbaf013f1632ca123fd528369932aef0d7f71cdd749ea1221c40ad1e4a44476
data/.travis.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - "2.0.0"
4
- - "2.1.1"
4
+ - "2.1.3"
5
5
  # uncomment this line if your project needs to run something other than `rake`:
6
6
  # # script: bundle exec rspec spec
data/Gemfile.lock CHANGED
@@ -1,50 +1,59 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- minionizer (0.0.1)
4
+ minionizer (0.2.0)
5
5
  activesupport (~> 4.1)
6
+ binding_of_caller (~> 0.7)
7
+ net-scp (~> 1.2)
6
8
  net-ssh (~> 2.9)
7
9
 
8
10
  GEM
9
11
  remote: http://rubygems.org/
10
12
  specs:
11
- activesupport (4.1.1)
13
+ activesupport (4.1.6)
12
14
  i18n (~> 0.6, >= 0.6.9)
13
15
  json (~> 1.7, >= 1.7.7)
14
16
  minitest (~> 5.1)
15
17
  thread_safe (~> 0.1)
16
18
  tzinfo (~> 1.1)
17
- coveralls (0.7.0)
19
+ binding_of_caller (0.7.2)
20
+ debug_inspector (>= 0.0.1)
21
+ coveralls (0.7.1)
18
22
  multi_json (~> 1.3)
19
23
  rest-client
20
24
  simplecov (>= 0.7)
21
25
  term-ansicolor
22
26
  thor
23
- docile (1.1.3)
24
- fakefs (0.5.2)
25
- i18n (0.6.9)
27
+ debug_inspector (0.0.2)
28
+ docile (1.1.5)
29
+ fakefs (0.6.0)
30
+ i18n (0.6.11)
26
31
  json (1.8.1)
27
32
  metaclass (0.0.4)
28
- mime-types (2.2)
29
- minitest (5.3.3)
30
- mocha (1.0.0)
33
+ mime-types (2.4.3)
34
+ minitest (5.4.2)
35
+ mocha (1.1.0)
31
36
  metaclass (~> 0.0.1)
32
- multi_json (1.10.0)
33
- net-ssh (2.9.0)
34
- rake (10.3.1)
35
- rest-client (1.6.7)
36
- mime-types (>= 1.16)
37
- simplecov (0.8.2)
37
+ multi_json (1.10.1)
38
+ net-scp (1.2.1)
39
+ net-ssh (>= 2.6.5)
40
+ net-ssh (2.9.1)
41
+ netrc (0.8.0)
42
+ rake (10.3.2)
43
+ rest-client (1.7.2)
44
+ mime-types (>= 1.16, < 3.0)
45
+ netrc (~> 0.7)
46
+ simplecov (0.9.1)
38
47
  docile (~> 1.1.0)
39
- multi_json
48
+ multi_json (~> 1.0)
40
49
  simplecov-html (~> 0.8.0)
41
50
  simplecov-html (0.8.0)
42
51
  term-ansicolor (1.3.0)
43
52
  tins (~> 1.0)
44
53
  thor (0.19.1)
45
- thread_safe (0.3.3)
46
- tins (1.1.0)
47
- tzinfo (1.1.0)
54
+ thread_safe (0.3.4)
55
+ tins (1.3.3)
56
+ tzinfo (1.2.2)
48
57
  thread_safe (~> 0.1)
49
58
 
50
59
  PLATFORMS
@@ -54,5 +63,6 @@ DEPENDENCIES
54
63
  coveralls
55
64
  fakefs (~> 0.5)
56
65
  minionizer!
66
+ minitest (~> 5.4)
57
67
  mocha (~> 1.0)
58
68
  rake (~> 10.3)
data/README.md CHANGED
@@ -9,9 +9,9 @@
9
9
  Minionizer aims to be a light weight, yet powerful, server provisioning tool with minimum learning
10
10
  curve.
11
11
 
12
- Minionizer is still in alpha development and is not yet ready for anything resembling production use.
12
+ Minionizer is still in beta development and is not yet ready for anything resembling production use.
13
13
 
14
- # Overview
14
+ ## Overview
15
15
 
16
16
  Minionizer allows you keep all of your provisioning "recipies" for a set of servers, along with any
17
17
  data those recipies may need (such as config files), in a single git repository.
@@ -31,27 +31,30 @@ packages, etc. You can use these core commands to build more complex recipies, o
31
31
  minionizer plugins that WILL BE available, such as posgresql installationi/upgrade, ruby
32
32
  installation/upgrade, etc.
33
33
 
34
- # Installation
34
+ ## Installation
35
35
 
36
36
  gem install minionizer
37
37
 
38
- # Usage
38
+ ## Demonstration
39
39
 
40
- ## Setup a new provisioning project in the current folder.
41
- Note: This step doesn't actually work yet.
40
+ A demonstration repo is available at [https://github.com/jsgarvin/minionizer-demo](https://github.com/jsgarvin/minionizer-demo).
41
+
42
+ ## Usage
43
+
44
+ ### Setup a new provisioning project in the current folder.
42
45
 
43
46
  minionize --init subfolder_name
44
47
 
45
48
  Creates `subfolder_name` and initializes it with some initial folders and files to get you started.
46
49
 
47
- ## Modify config/minions.yml
50
+ ### Modify config/minions.yml
48
51
 
49
52
  The minions.yml file is where you define what servers this project will manage and what roles
50
53
  each server will play.
51
54
 
52
55
  You will probably want assign each server multiple roles, such as `['production', 'db']`.
53
56
 
54
- ## Create role instructions
57
+ ### Create role instructions
55
58
 
56
59
  A sample role file WILL BE provided in the ./roles folder to get you started. Each role file defines
57
60
  what servers assigned that role should do on each (re)provisioning.
@@ -61,7 +64,7 @@ file. You will likely have some roles, such as "production", that are mearly a m
61
64
  several servers together and won't have a corresponding role file. You will need at least one role,
62
65
  though, such as "db" or "webserver", that will have a corresponding role file.
63
66
 
64
- ## Provision Servers
67
+ ### Provision Servers
65
68
 
66
69
  To provision all of the servers that are assigned a particular role, run...
67
70
 
@@ -79,7 +82,7 @@ or
79
82
  This will loop through each role that is assigned to just that server, and any corresponding role
80
83
  files will be run.
81
84
 
82
- # Contribute
85
+ ## Contribute
83
86
 
84
87
  To contribute to Minionizer development you will need to install [vagrant](http://www.vagrantup.com/)
85
88
  and [VirtualBox](https://www.virtualbox.org/) in order to be able to run acceptance tests.
data/Rakefile CHANGED
@@ -14,6 +14,7 @@ end
14
14
 
15
15
  namespace :test do
16
16
  namespace :vm do
17
+ desc 'Start Test VM'
17
18
  task :start do
18
19
  relay_output(vagrant_command(:up))
19
20
  unless snapshot_plugin_installed?
@@ -24,6 +25,7 @@ namespace :test do
24
25
  relay_output(vagrant_command('snapshot take blank-test-slate'))
25
26
  end
26
27
  end
28
+ desc 'Stop Test VM'
27
29
  task :stop do
28
30
  relay_output(vagrant_command(:halt))
29
31
  end
data/bin/minionize CHANGED
@@ -1,3 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  require_relative '../lib/minionizer'
3
- Minionizer::Minionization.new(ARGV, Minionizer::Configuration.instance).call
3
+ if ARGV[0] == '--init'
4
+ Minionizer::Initialization.create(ARGV[1])
5
+ elsif ['-gk','--generate-key'].include?(ARGV[0])
6
+ Minionizer::Cryptographer.new.generate_key
7
+ elsif ['-es','--encrypt-secrets'].include?(ARGV[0])
8
+ Minionizer::Cryptographer.new.encrypt_secrets
9
+ elsif ['-ds','--decrypt-secrets'].include?(ARGV[0])
10
+ Minionizer::Cryptographer.new.decrypt_secrets
11
+ else
12
+ Minionizer::Minionization.new(ARGV, Minionizer::Configuration.instance).call
13
+ end
@@ -3,7 +3,7 @@ module Minionizer
3
3
 
4
4
  def call
5
5
  session.exec("mkdir --parents #{target_directory}")
6
- session.exec("echo '#{contents_from(source_path)}' > #{target_path}")
6
+ session.scp(string_io_creator.new(contents), target_path)
7
7
  session.exec("chmod #{mode} #{target_path}") if respond_to?(:mode)
8
8
  session.exec("chown #{owner} #{target_path}") if respond_to?(:owner)
9
9
  session.exec("chgrp #{group} #{target_path}") if respond_to?(:group)
@@ -17,8 +17,36 @@ module Minionizer
17
17
  File.dirname(target_path)
18
18
  end
19
19
 
20
- def contents_from(source)
21
- File.open(source).read.strip
20
+ def contents
21
+ options[:contents] ||= processed_contents_from_source_path
22
+ end
23
+
24
+ def processed_contents_from_source_path
25
+ if source_file_requires_erb_processing?
26
+ ERB.new(contents_from_source_path).result(erb_binding)
27
+ else
28
+ contents_from_source_path
29
+ end
30
+ end
31
+
32
+ def source_file_requires_erb_processing?
33
+ File.extname(source_path) == '.erb'
34
+ end
35
+
36
+ def contents_from_source_path
37
+ File.open(source_path).read.strip
38
+ end
39
+
40
+ def erb_binding
41
+ level = 1
42
+ until binding.of_caller(level).eval('self.class') != self.class
43
+ level += 1
44
+ end
45
+ binding.of_caller(level)
46
+ end
47
+
48
+ def string_io_creator
49
+ options[:string_io_creator] ||= StringIO
22
50
  end
23
51
  end
24
52
  end
@@ -2,36 +2,57 @@ module Minionizer
2
2
  class PublicSshKeyInjection < TaskTemplate
3
3
 
4
4
  def call
5
+ folder_creation.call
5
6
  file_injection.call
6
- ensure
7
- temp_file.unlink
8
7
  end
9
8
 
10
9
  #######
11
10
  private
12
11
  #######
13
12
 
13
+ def folder_creation
14
+ @folder_creation ||= folder_creation_creator.new(session, folder_creation_options)
15
+ end
16
+
14
17
  def file_injection
15
18
  @file_injection ||= file_injection_creator.new(session, file_injection_options)
16
19
  end
17
20
 
21
+ def folder_creation_creator
22
+ options[:folder_creation_creator] ||= FolderCreation
23
+ end
24
+
18
25
  def file_injection_creator
19
26
  options[:file_injection_creator] ||= FileInjection
20
27
  end
21
28
 
29
+ def folder_creation_options
30
+ {
31
+ path: target_folder,
32
+ owner: target_username,
33
+ group: target_username,
34
+ mode: 700
35
+ }
36
+ end
37
+
22
38
  def file_injection_options
23
39
  {
24
- source_path: temp_file.path,
25
- target_path: "~#{target_username}/.ssh/authorized_keys",
40
+ contents: combined_keys,
41
+ target_path: "#{target_folder}/authorized_keys",
26
42
  owner: target_username,
27
- group: target_username
43
+ group: target_username,
44
+ mode: 600
28
45
  }
29
46
  end
30
47
 
31
- def temp_file
32
- @temp_file ||= Tempfile.new('MinionizerPublicKeys').tap do |temp_file|
48
+ def target_folder
49
+ "/home/#{target_username}/.ssh"
50
+ end
51
+
52
+ def combined_keys
53
+ String.new.tap do |string|
33
54
  Dir.glob("data/public_keys/*.pubkey") do |key_file|
34
- temp_file.puts File.open(key_file).read
55
+ string << File.open(key_file).read
35
56
  end
36
57
  end
37
58
  end
@@ -19,6 +19,9 @@ module Minionizer
19
19
  options.key?(method_name) || super
20
20
  end
21
21
 
22
+ def download_file(source, destination)
23
+ session.exec(%Q{bash -c "mkdir -p #{destination}; cd #{destination}; wget -nc #{source}"})
24
+ end
22
25
  end
23
26
  end
24
27
 
@@ -4,11 +4,12 @@ module Minionizer
4
4
  class CommandError < StandardError; end
5
5
  class InvocationError < StandardError; end
6
6
 
7
- attr_reader :connection, :command
7
+ attr_reader :connection, :command, :options
8
8
 
9
- def initialize(connection, command)
9
+ def initialize(connection, command, options={})
10
10
  @connection = connection
11
11
  @command = command
12
+ @options = options
12
13
  end
13
14
 
14
15
  def call
@@ -27,6 +28,7 @@ module Minionizer
27
28
  end
28
29
 
29
30
  def execute_command_inside_channel(channel)
31
+ inform("Running: #{command}")
30
32
  channel.exec(command) do |_, success|
31
33
  if success
32
34
  compile_results(channel)
@@ -51,10 +53,21 @@ module Minionizer
51
53
  end
52
54
 
53
55
  def compile_results(channel)
54
- channel.on_data { |_, data| results[:stdout] += data.strip }
55
- channel.on_extended_data { |_, data| results[:stderr] += data.to_s }
56
+ read_stdout(channel)
57
+ channel.on_extended_data { |_, _, data| results[:stderr] += data.to_s }
56
58
  channel.on_request('exit-status') { |_,data| results[:exit_code] = data.read_long }
57
59
  channel.on_request('exit-signal') { |_,data| results[:exit_signal] = data.read_string }
58
60
  end
61
+
62
+ def read_stdout(channel)
63
+ channel.on_data do |_, data|
64
+ inform("STDOUT: #{data}")
65
+ results[:stdout] += data.strip
66
+ end
67
+ end
68
+
69
+ def inform(message)
70
+ puts message if options[:verbose]
71
+ end
59
72
  end
60
73
  end
@@ -0,0 +1,84 @@
1
+ module Minionizer
2
+ class Cryptographer
3
+ KEYRING_PATH = './data/public_keyring.gpg'
4
+ SECRET_FOLDER = './data/secrets'
5
+ SAFE_FOLDER = './data/encrypted_secrets'
6
+
7
+ def generate_key
8
+ system("#{gpg_command} --gen-key")
9
+ end
10
+
11
+ def encrypt_secrets
12
+ Dir.foreach(SECRET_FOLDER) do |filename|
13
+ next if ['.','..'].include?(filename)
14
+ encrypt_and_rehash(filename)
15
+ end
16
+ end
17
+
18
+ def decrypt_secrets
19
+ Dir.foreach(SAFE_FOLDER) do |filename|
20
+ next unless filename.match(/\.enc$/)
21
+ decrypt(filename)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def encrypt_and_rehash(filename)
28
+ if shas_match?(filename)
29
+ puts "Skipping: #{filename} (shas match)"
30
+ else
31
+ puts "Encrypting: #{filename}"
32
+ system("#{gpg_command} --output #{SAFE_FOLDER}/#{filename}.enc #{recipient_args.join(' ')} --encrypt #{SECRET_FOLDER}/#{filename}")
33
+ hash(filename)
34
+ end
35
+ end
36
+
37
+ def hash(filename)
38
+ puts "Hashing: #{filename}"
39
+ system("sha512sum #{SECRET_FOLDER}/#{filename} > #{SAFE_FOLDER}/#{filename}.sha")
40
+ end
41
+
42
+ def decrypt(filename)
43
+ if shas_match?(decrypted_filename(filename))
44
+ puts "Skipping: #{filename} (shas match)"
45
+ else
46
+ puts "Decrypting: #{filename}"
47
+ system("#{gpg_command} --output #{SECRET_FOLDER}/#{decrypted_filename(filename)} --decrypt #{SAFE_FOLDER}/#{filename}")
48
+ end
49
+ end
50
+
51
+ def recipient_args
52
+ recipient_fingerprints.split("\n").map {|fingerprint| "--recipient #{fingerprint}" }
53
+ end
54
+
55
+ def recipient_fingerprints
56
+ "fingerprint\n"
57
+ `#{gpg_command} --fingerprint --with-colons | grep fpr | cut -d ":" -f10`
58
+ end
59
+
60
+ def decrypted_filename(filename)
61
+ filename.match(/(.+)\.enc$/)[1]
62
+ end
63
+
64
+ def gpg_command
65
+ "gpg --keyring #{KEYRING_PATH} --no-default-keyring"
66
+ end
67
+
68
+ def shas_match?(filename)
69
+ File.exists?(stored_sha_path(filename)) && local_sha(filename) == stored_sha(filename)
70
+ end
71
+
72
+ def local_sha(filename)
73
+ `sha512sum #{SECRET_FOLDER}/#{filename}`
74
+ end
75
+
76
+ def stored_sha(filename)
77
+ `cat #{stored_sha_path(filename)}`
78
+ end
79
+
80
+ def stored_sha_path(filename)
81
+ "#{SAFE_FOLDER}/#{filename}.sha"
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,55 @@
1
+ module Minionizer
2
+ class Initialization
3
+ SUBFOLDERS = [
4
+ '', #root folder
5
+ '/config',
6
+ '/data/encrypted_secrets',
7
+ '/data/public_keys',
8
+ '/data/secrets',
9
+ '/lib',
10
+ '/roles'
11
+ ]
12
+
13
+ attr_reader :path
14
+
15
+ def self.create(path)
16
+ new(path).save
17
+ end
18
+
19
+ def initialize(path)
20
+ @path = path
21
+ end
22
+
23
+ def save
24
+ create_directory_structure
25
+ touch_config
26
+ ignore_secrets
27
+ end
28
+
29
+ private
30
+
31
+ def create_directory_structure
32
+ SUBFOLDERS.each do |folder|
33
+ system("mkdir -p #{path}#{folder}")
34
+ end
35
+ end
36
+
37
+ def touch_config
38
+ system("touch #{path}/config/minions.yml")
39
+ end
40
+
41
+ def ignore_secrets
42
+ system("touch #{gitignore_path}")
43
+ system("echo 'data/secrets' > #{gitignore_path}") unless secrets_ignored?
44
+ end
45
+
46
+ def secrets_ignored?
47
+ File.readlines(gitignore_path).grep(/^data\/secrets$/).any?
48
+ end
49
+
50
+ def gitignore_path
51
+ "#{path}/.gitignore"
52
+ end
53
+
54
+ end
55
+ end
@@ -1,12 +1,14 @@
1
+ require 'securerandom'
1
2
  module Minionizer
2
3
  class Session
3
- attr_reader :fqdn, :username, :password, :connector, :command_executor
4
+ attr_reader :fqdn, :username, :password, :ssh_connector, :scp_connector, :command_executor
4
5
 
5
- def initialize(fqdn, credentials, connector = Net::SSH, command_executor = CommandExecution)
6
+ def initialize(fqdn, credentials, ssh_connector=Net::SSH, scp_connector=Net::SCP, command_executor=CommandExecution)
6
7
  @fqdn = fqdn
7
8
  @username = credentials['username']
8
9
  @password = credentials['password']
9
- @connector = connector
10
+ @ssh_connector = ssh_connector
11
+ @scp_connector = scp_connector
10
12
  @command_executor = command_executor
11
13
  end
12
14
 
@@ -22,26 +24,33 @@ module Minionizer
22
24
  end
23
25
 
24
26
  def exec(*commands)
25
- results = commands.map { |command| execution(command).call }
27
+ options = commands.last.is_a?(Hash) ? commands.pop : {}
28
+ results = commands.map { |command| execution(command, options).call }
26
29
  results.length == 1 ? results.first : results
27
30
  end
28
31
 
32
+ def scp(local_path, remote_path)
33
+ if with_sudo?
34
+ tmp_filename = "#{SecureRandom.hex}.minionizer_tempfile"
35
+ scp_connection.upload!(local_path, "#{tmp_filename}")
36
+ exec("mv #{tmp_filename} #{remote_path}")
37
+ else
38
+ scp_connection.upload!(local_path, remote_path)
39
+ end
40
+ end
41
+
29
42
  #######
30
43
  private
31
44
  #######
32
45
 
33
- def execution(command)
46
+ def execution(command, options={})
34
47
  if with_sudo?
35
- command_executor.new(connection, prefix_sudo(command))
48
+ command_executor.new(ssh_connection, prefix_sudo(command), options)
36
49
  else
37
- command_executor.new(connection, command)
50
+ command_executor.new(ssh_connection, command, options)
38
51
  end
39
52
  end
40
53
 
41
- def connection
42
- @connection ||= connector.start(fqdn, username, password: password)
43
- end
44
-
45
54
  def prefix_sudo(command)
46
55
  %Q{sudo bash -c "#{command}"}
47
56
  end
@@ -50,5 +59,13 @@ module Minionizer
50
59
  @with_sudo
51
60
  end
52
61
 
62
+ def ssh_connection
63
+ @ssh_connection ||= ssh_connector.start(fqdn, username, password: password)
64
+ end
65
+
66
+ def scp_connection
67
+ @scp_connection ||= scp_connector.start(fqdn, username, password: password)
68
+ end
69
+
53
70
  end
54
71
  end
@@ -1,3 +1,3 @@
1
1
  module Minionizer
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/minionizer.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'active_support/core_ext/hash/indifferent_access'
2
2
  require 'active_support/inflector'
3
+ require 'binding_of_caller'
3
4
  require 'erb'
5
+ require 'net/scp'
4
6
  require 'net/ssh'
5
7
  require 'singleton'
6
8
  require 'yaml'
data/minionizer.gemspec CHANGED
@@ -11,10 +11,13 @@ Gem::Specification.new do |s|
11
11
  s.description = %q{Minionizer aims to be a light weight server provisioning tool without bloat or steep learning curves.}
12
12
 
13
13
  s.add_dependency('activesupport', '~> 4.1')
14
+ s.add_dependency('binding_of_caller', '~> 0.7')
14
15
  s.add_dependency('net-ssh', '~> 2.9')
16
+ s.add_dependency('net-scp', '~> 1.2')
15
17
 
16
18
  s.add_development_dependency('fakefs', '~> 0.5')
17
19
  s.add_development_dependency('mocha', '~> 1.0')
20
+ s.add_development_dependency('minitest', '~> 5.4')
18
21
  s.add_development_dependency('rake', '~> 10.3')
19
22
 
20
23
  s.files = `git ls-files`.split("\n")
@@ -88,8 +88,8 @@ module Minionizer
88
88
  group: ownername
89
89
  }}
90
90
  let(:code) { %Q{
91
- session.sudo do
92
- Minionizer::FileInjection.new( session, #{options}).call
91
+ session.sudo do |sudo_session|
92
+ Minionizer::FileInjection.new(sudo_session, #{options}).call
93
93
  end
94
94
  } }
95
95
 
@@ -107,6 +107,7 @@ module Minionizer
107
107
  it 'injects a file' do
108
108
  2.times { assert_throws(:high_five) { minionization.call } }
109
109
  assert_file_exists(target_path)
110
+ assert_equal('FooBar', session.sudo("cat #{target_path}")[:stdout])
110
111
  mode = session.exec("stat --format=%a #{target_path}")[:stdout]
111
112
  assert_equal('700',mode)
112
113
  owner = session.exec("stat --format=%U #{target_path}")[:stdout]
@@ -137,11 +138,15 @@ module Minionizer
137
138
  after do
138
139
  File.delete("#{source_path}/foobar.pubkey")
139
140
  File.delete("#{source_path}/foobaz.pubkey")
141
+ skip unless minion_available?
142
+ session.sudo("userdel #{target_username}")
140
143
  end
141
144
 
142
145
  it 'injects public keys' do
143
146
  2.times { assert_throws(:high_five) { minionization.call } }
144
- assert_file_exists("~#{target_username}/.ssh/authorized_keys")
147
+ assert_file_exists("/home/#{target_username}/.ssh/authorized_keys")
148
+ assert_match(/FooBar/, session.sudo("cat ~#{target_username}/.ssh/authorized_keys")[:stdout])
149
+ assert_match(/FooBaz/, session.sudo("cat ~#{target_username}/.ssh/authorized_keys")[:stdout])
145
150
  end
146
151
  end
147
152
 
@@ -173,7 +178,7 @@ module Minionizer
173
178
  end
174
179
 
175
180
  def link_exists?(path, parameter = :e)
176
- session.exec("[ -#{parameter} #{path} ] && echo 'yes' || echo 'no'")[:stdout] == 'yes'
181
+ session.sudo("[ -#{parameter} #{path} ] && echo 'yes' || echo 'no'")[:stdout] == 'yes'
177
182
  end
178
183
 
179
184
  def assert_user_exists(username)
data/test/test_helper.rb CHANGED
@@ -4,7 +4,6 @@ require 'coveralls'
4
4
  require 'minitest/autorun'
5
5
  require 'fakefs/safe'
6
6
  require 'socket'
7
- require 'tempfile'
8
7
  require 'timeout'
9
8
 
10
9
  if Coveralls.will_run?