machines 0.5.4 → 0.5.6
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.
- data/.yardopts +7 -1
- data/CHANGELOG.md +16 -4
- data/INSTALL.md +3 -0
- data/LICENSE +1 -2
- data/README.md +47 -28
- data/Rakefile +0 -8
- data/TODO.md +66 -59
- data/bin/machines +1 -2
- data/lib/machines.rb +16 -1
- data/lib/machines/app_settings.rb +1 -1
- data/lib/machines/cloud_machine.rb +1 -1
- data/lib/machines/command.rb +0 -2
- data/lib/machines/commandline.rb +23 -29
- data/lib/machines/commands/checks.rb +67 -0
- data/lib/machines/commands/configuration.rb +50 -0
- data/lib/machines/commands/database.rb +18 -0
- data/lib/machines/commands/file_operations.rb +105 -0
- data/lib/machines/commands/installation.rb +184 -0
- data/lib/machines/commands/questions.rb +16 -0
- data/lib/machines/commands/services.rb +26 -0
- data/lib/machines/core.rb +55 -25
- data/lib/machines/logger.rb +0 -2
- data/lib/machines/named_buffer.rb +7 -6
- data/lib/machines/version.rb +1 -1
- data/lib/packages/awstats.rb +2 -2
- data/lib/packages/docky.rb +0 -1
- data/lib/packages/dwm.rb +5 -0
- data/lib/packages/nginx_logrotate.rb +2 -2
- data/lib/packages/timezone.rb +2 -4
- data/lib/template/Machinesfile +2 -1
- data/lib/template/config.yml +3 -0
- data/spec/lib/machines/app_settings_spec.rb +13 -12
- data/spec/lib/machines/cloud_machine_spec.rb +9 -8
- data/spec/lib/machines/commandline_spec.rb +69 -90
- data/spec/lib/machines/{checks_spec.rb → commands/checks_spec.rb} +1 -1
- data/spec/lib/machines/{configuration_spec.rb → commands/configuration_spec.rb} +2 -3
- data/spec/lib/machines/{database_spec.rb → commands/database_spec.rb} +4 -10
- data/spec/lib/machines/{file_operations_spec.rb → commands/file_operations_spec.rb} +3 -7
- data/spec/lib/machines/{installation_spec.rb → commands/installation_spec.rb} +10 -4
- data/spec/lib/machines/{questions_spec.rb → commands/questions_spec.rb} +1 -3
- data/spec/lib/machines/{services_spec.rb → commands/services_spec.rb} +1 -4
- data/spec/lib/machines/core_spec.rb +81 -65
- data/spec/lib/packages/abiword_spec.rb +1 -5
- data/spec/lib/packages/amazon_mp3_spec.rb +0 -4
- data/spec/lib/packages/awstats_spec.rb +3 -4
- data/spec/lib/packages/base_spec.rb +0 -1
- data/spec/lib/packages/chrome_spec.rb +0 -4
- data/spec/lib/packages/cruisecontrol_spec.rb +1 -2
- data/spec/lib/packages/dependencies_spec.rb +1 -2
- data/spec/lib/packages/docky_spec.rb +0 -4
- data/spec/lib/packages/dotfiles_spec.rb +5 -4
- data/spec/lib/packages/dwm_spec.rb +23 -0
- data/spec/lib/packages/file_roller_spec.rb +1 -5
- data/spec/lib/packages/firefox_spec.rb +0 -4
- data/spec/lib/packages/gedit_spec.rb +1 -5
- data/spec/lib/packages/git_spec.rb +0 -4
- data/spec/lib/packages/gmate_spec.rb +1 -5
- data/spec/lib/packages/gnome_spec.rb +0 -4
- data/spec/lib/packages/gnumeric_spec.rb +1 -5
- data/spec/lib/packages/hosts_spec.rb +0 -1
- data/spec/lib/packages/load_machines_spec.rb +16 -15
- data/spec/lib/packages/monit_spec.rb +0 -1
- data/spec/lib/packages/mysql_spec.rb +1 -3
- data/spec/lib/packages/nginx_logrotate_spec.rb +17 -18
- data/spec/lib/packages/nginx_spec.rb +0 -1
- data/spec/lib/packages/openbox_spec.rb +0 -4
- data/spec/lib/packages/passenger_nginx_spec.rb +0 -1
- data/spec/lib/packages/passenger_spec.rb +0 -1
- data/spec/lib/packages/postfix_spec.rb +1 -5
- data/spec/lib/packages/questions_spec.rb +3 -4
- data/spec/lib/packages/rbenv_spec.rb +1 -4
- data/spec/lib/packages/rvm_spec.rb +1 -4
- data/spec/lib/packages/save_machines_spec.rb +0 -1
- data/spec/lib/packages/slim_spec.rb +1 -2
- data/spec/lib/packages/sqlserver_spec.rb +0 -4
- data/spec/lib/packages/timezone_spec.rb +2 -3
- data/spec/lib/packages/unison_spec.rb +1 -2
- data/spec/lib/packages/virtualbox_guest_spec.rb +0 -4
- data/spec/lib/packages/virtualbox_spec.rb +1 -2
- data/spec/lib/packages/webapps_spec.rb +1 -3
- data/spec/spec_helper.rb +59 -61
- data/spec/support/minitest.rb +4 -62
- metadata +27 -28
- data/lib/machines/base.rb +0 -13
- data/lib/machines/checks.rb +0 -63
- data/lib/machines/configuration.rb +0 -49
- data/lib/machines/database.rb +0 -17
- data/lib/machines/file_operations.rb +0 -104
- data/lib/machines/installation.rb +0 -171
- data/lib/machines/machinesfile.rb +0 -25
- data/lib/machines/questions.rb +0 -15
- data/lib/machines/services.rb +0 -24
- data/spec/lib/machines/machinesfile_spec.rb +0 -34
@@ -0,0 +1,16 @@
|
|
1
|
+
module Machines
|
2
|
+
module Commands
|
3
|
+
module Questions
|
4
|
+
def enter_password(type, confirm = true)
|
5
|
+
begin
|
6
|
+
password = ask("Enter #{type} password: ") { |question| question.echo = false }
|
7
|
+
break unless confirm
|
8
|
+
password_confirmation = ask('Confirm the password: ') { |question| question.echo = false }
|
9
|
+
say "Passwords do not match, please re-enter" unless password == password_confirmation
|
10
|
+
end while password != password_confirmation
|
11
|
+
$conf.passwords << password if $conf.passwords && password.size > 4 && password != 'password'
|
12
|
+
password
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Machines
|
2
|
+
module Commands
|
3
|
+
module Services
|
4
|
+
# Stop a daemon
|
5
|
+
# @param [String] daemon Name of the service to stop
|
6
|
+
def stop daemon
|
7
|
+
Command.new("service #{daemon} stop", check_daemon(daemon, false))
|
8
|
+
end
|
9
|
+
|
10
|
+
# Start a daemon
|
11
|
+
# @param [String] daemon Name of the service to start
|
12
|
+
# @param [Hash] options
|
13
|
+
# @option options [Boolean] :check Set to false to disable the check (e.g. start hostname, :check => false)
|
14
|
+
def start daemon, options = {}
|
15
|
+
check = options[:check] || check_daemon(daemon)
|
16
|
+
Command.new("service #{daemon} start", check)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Restart a daemon
|
20
|
+
# @param [String] daemon Name of the service to restart
|
21
|
+
def restart daemon
|
22
|
+
Command.new("service #{daemon} restart", check_daemon(daemon))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/machines/core.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
module Machines
|
2
|
-
|
2
|
+
class Core
|
3
|
+
include Commands::Checks
|
4
|
+
include Commands::Configuration
|
5
|
+
include Commands::Database
|
6
|
+
include Commands::FileOperations
|
7
|
+
include Commands::Installation
|
8
|
+
include Commands::Questions
|
9
|
+
include Commands::Services
|
10
|
+
|
3
11
|
# If a block is given, store the task, log it and run it
|
4
12
|
# If no block is given, sets commands to only those of the specified tasks so they can be run standalone
|
5
13
|
# @param [Symbol, String, Array] name Name of the task or array of task names
|
@@ -26,12 +34,6 @@ module Machines
|
|
26
34
|
$conf.tasks[name] = {:description => description, :block => block}
|
27
35
|
end
|
28
36
|
|
29
|
-
def list_tasks
|
30
|
-
$conf.tasks.each do |name, task|
|
31
|
-
say " #{"%-20s" % name}#{task[:description]}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
37
|
def generate_password
|
36
38
|
WEBrick::Utils.random_string(20)
|
37
39
|
end
|
@@ -46,25 +48,22 @@ module Machines
|
|
46
48
|
yield unless matched(options)
|
47
49
|
end
|
48
50
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
return unless value == $conf[key].to_s
|
64
|
-
end
|
65
|
-
end
|
51
|
+
def load_app_settings(apps)
|
52
|
+
AppSettings.new.load_app_settings(apps)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Loads the Machinesfile or a package
|
56
|
+
def package name
|
57
|
+
if name == 'Machinesfile'
|
58
|
+
custom_name = builtin_name = 'Machinesfile'
|
59
|
+
error = "Cannot find 'Machinesfile'. Use `machines new` to create a template."
|
60
|
+
else
|
61
|
+
custom_name = File.join('packages', "#{name}.rb")
|
62
|
+
builtin_name = File.join($conf.application_dir, 'packages', "#{name}.rb")
|
63
|
+
error = "Cannot find custom or built-in package '#{name}'."
|
66
64
|
end
|
67
|
-
|
65
|
+
package = load_and_eval(custom_name) || load_and_eval(builtin_name)
|
66
|
+
package || raise(LoadError, error, caller)
|
68
67
|
end
|
69
68
|
|
70
69
|
# Queue up command(s) to run remotely
|
@@ -112,9 +111,40 @@ module Machines
|
|
112
111
|
end
|
113
112
|
end
|
114
113
|
|
114
|
+
#TODO: Move matched into separate class to test
|
115
|
+
def matched options
|
116
|
+
options.each do |key, value|
|
117
|
+
value = value.is_a?(Array) ? value.map{|o| o.to_s } : value.to_s
|
118
|
+
if $conf[key].is_a?(Array)
|
119
|
+
values = $conf[key].map{|o| o.to_s }
|
120
|
+
if value.is_a?(Array)
|
121
|
+
return unless values.reject{ |symbol| !value.include?(symbol.to_s) }.any?
|
122
|
+
else
|
123
|
+
return unless values.include?(value)
|
124
|
+
end
|
125
|
+
else
|
126
|
+
if value.is_a?(Array)
|
127
|
+
return unless value.include?($conf[key].to_s)
|
128
|
+
else
|
129
|
+
return unless value == $conf[key].to_s
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def load_and_eval package_name
|
138
|
+
if File.exists?(package_name)
|
139
|
+
eval(File.read(package_name), nil, "eval: #{package_name}")
|
140
|
+
true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
115
144
|
def command_from_string commands
|
116
145
|
commands.first.is_a?(String) ? [Command.new(commands[0], commands[1])] : commands
|
117
146
|
end
|
147
|
+
|
118
148
|
end
|
119
149
|
end
|
120
150
|
|
data/lib/machines/logger.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Machines
|
2
|
+
class NamedBuffer < StringIO
|
3
|
+
attr_reader :name
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def initialize name, string
|
6
|
+
super string
|
7
|
+
@name = name
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
|
-
|
data/lib/machines/version.rb
CHANGED
data/lib/packages/awstats.rb
CHANGED
@@ -4,7 +4,7 @@ task :awstats, 'Install AWStats' do
|
|
4
4
|
local_file = '/usr/local/bin/awstats_render'
|
5
5
|
sudo "wget #{remote_file} -O #{local_file}", check_file(local_file)
|
6
6
|
sudo chmod '+x', local_file
|
7
|
-
|
7
|
+
|
8
8
|
$conf.webapps.each do |app_name, app|
|
9
9
|
stats_path = "/etc/awstats/awstats.#{app.server_name}.conf"
|
10
10
|
sudo create_from 'misc/awstats.conf.erb', settings: app, to: stats_path
|
@@ -13,4 +13,4 @@ task :awstats, 'Install AWStats' do
|
|
13
13
|
run mkdir "#{app_stats}/public"
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
data/lib/packages/docky.rb
CHANGED
data/lib/packages/dwm.rb
ADDED
@@ -7,7 +7,7 @@ task :logrotate_nginx, 'Logrotate nginx access and error logs and optionally gen
|
|
7
7
|
else
|
8
8
|
stats_prerotate = stats_postrotate = nil
|
9
9
|
end
|
10
|
-
settings =
|
10
|
+
settings = AppSettings::AppBuilder.new(
|
11
11
|
log_path: "/var/log/nginx/#{app.name}.#{type}.log",
|
12
12
|
stats_prerotate: stats_prerotate,
|
13
13
|
stats_postrotate: stats_postrotate
|
@@ -19,7 +19,7 @@ end
|
|
19
19
|
|
20
20
|
task :logrotate_apps, 'Logrotate Rails app logs' do
|
21
21
|
$conf.webapps.each do |app_name, app|
|
22
|
-
settings =
|
22
|
+
settings = AppSettings::AppBuilder.new(log_path: File.join(app.path, 'shared', 'log', '*.log'))
|
23
23
|
sudo create_from 'logrotate/app.erb', settings: settings, to: File.join('/etc', 'logrotate.d', "#{app.name}_app")
|
24
24
|
end
|
25
25
|
end
|
data/lib/packages/timezone.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
task :timezone, 'Set timezone from config.yml' do
|
2
|
-
sudo link
|
3
|
-
|
4
|
-
# Ensure UTC is used or not
|
2
|
+
sudo link "/usr/share/zoneinfo/#{$conf.timezone}", '/etc/localtime'
|
3
|
+
# Ensure UTC is configured
|
5
4
|
if !$conf.clock_utc.nil?
|
6
5
|
options = {false => 'no', true => 'yes'}
|
7
6
|
sudo replace "UTC=#{options[!$conf.clock_utc]}", :with => "UTC=#{options[$conf.clock_utc]}", :in => '/etc/default/rcS'
|
8
7
|
end
|
9
8
|
end
|
10
|
-
|
data/lib/template/Machinesfile
CHANGED
data/lib/template/config.yml
CHANGED
@@ -23,6 +23,9 @@ cloud:
|
|
23
23
|
aws_access_key_id: 123
|
24
24
|
aws_secret_access_key: 456
|
25
25
|
|
26
|
+
dwm:
|
27
|
+
version: 6.0
|
28
|
+
|
26
29
|
# IP hosts. These are added to /etc/hosts by the hosts task in the base package
|
27
30
|
# They are also added to known hosts but the host must be accessible at this point
|
28
31
|
# Note:
|
@@ -1,13 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
3
|
+
describe AppSettings do
|
4
|
+
|
5
|
+
subject { AppSettings.new }
|
5
6
|
|
6
7
|
describe 'load_and_generate_passwords_for_webapps' do
|
7
8
|
it 'generates passwords and saves to webapps.yml' do
|
8
9
|
File.open('webapps.yml', 'w') {|f| f.puts "###\n\n---\nwebapps:\n my_app:\n development:\n password: \n" }
|
9
|
-
stubs(:generate_password).returns 'random'
|
10
|
-
load_and_generate_passwords_for_webapps
|
10
|
+
subject.stubs(:generate_password).returns 'random'
|
11
|
+
subject.load_and_generate_passwords_for_webapps
|
11
12
|
File.read('webapps.yml').must_equal "###\n\n---\nwebapps:\n my_app:\n development:\n password: random\n"
|
12
13
|
end
|
13
14
|
end
|
@@ -30,9 +31,9 @@ EOF
|
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'loads the app settings for selected apps' do
|
33
|
-
load_app_settings ['app']
|
34
|
+
subject.load_app_settings ['app']
|
34
35
|
$conf.webapps.must_equal({
|
35
|
-
'app' => AppBuilder.new(
|
36
|
+
'app' => AppSettings::AppBuilder.new(
|
36
37
|
:scm => 'scm://project.git',
|
37
38
|
:name => 'app',
|
38
39
|
:path => '/home/user/app',
|
@@ -45,9 +46,9 @@ EOF
|
|
45
46
|
|
46
47
|
it 'handles ssl settings' do
|
47
48
|
File.open('webapps.yml', 'w') {|f| f.puts @settings }
|
48
|
-
load_app_settings ['app']
|
49
|
+
subject.load_app_settings ['app']
|
49
50
|
$conf.webapps.must_equal({
|
50
|
-
'app' => AppBuilder.new(
|
51
|
+
'app' => AppSettings::AppBuilder.new(
|
51
52
|
:name => 'app',
|
52
53
|
:scm => 'scm://project.git',
|
53
54
|
:path => '/home/user/app',
|
@@ -64,7 +65,7 @@ EOF
|
|
64
65
|
|
65
66
|
it 'does not fail when settings not included for specified environment' do
|
66
67
|
File.open('webapps.yml', 'w') {|f| f.puts "---\nwebapps:\n app:\n path: path\n" }
|
67
|
-
load_app_settings(['app'])
|
68
|
+
subject.load_app_settings(['app'])
|
68
69
|
end
|
69
70
|
|
70
71
|
it 'loads settings for all apps when none specified' do
|
@@ -83,16 +84,16 @@ webapps:
|
|
83
84
|
password: secure
|
84
85
|
EOF
|
85
86
|
File.open('webapps.yml', 'w') {|f| f.puts settings }
|
86
|
-
load_app_settings nil
|
87
|
+
subject.load_app_settings nil
|
87
88
|
$conf.webapps.must_equal({
|
88
|
-
'app' => AppBuilder.new(
|
89
|
+
'app' => AppSettings::AppBuilder.new(
|
89
90
|
:name => 'app',
|
90
91
|
:path => '/home/user/app',
|
91
92
|
:scm => 'scm://project.git',
|
92
93
|
:root => '/home/user/app/current/public',
|
93
94
|
:setting => 'setting',
|
94
95
|
:password => 'secure'),
|
95
|
-
'other' => AppBuilder.new(
|
96
|
+
'other' => AppSettings::AppBuilder.new(
|
96
97
|
:name => 'other',
|
97
98
|
:root => '/home/user/other/current/public',
|
98
99
|
:scm => 'scm://other_project',
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'fog'
|
3
3
|
|
4
|
-
describe
|
5
|
-
|
4
|
+
describe CloudMachine do
|
5
|
+
|
6
|
+
subject { CloudMachine.new }
|
6
7
|
|
7
8
|
before do
|
8
9
|
Fog.mock!
|
@@ -11,11 +12,11 @@ describe 'CloudMachine' do
|
|
11
12
|
end
|
12
13
|
|
13
14
|
it 'displays an error message when fog gem is not available' do
|
14
|
-
stubs(:require)
|
15
|
-
expects(:require).with('fog').raises LoadError
|
15
|
+
subject.stubs(:require)
|
16
|
+
subject.expects(:require).with('fog').raises LoadError
|
16
17
|
lambda do
|
17
18
|
begin
|
18
|
-
connect_to_cloud
|
19
|
+
subject.connect_to_cloud
|
19
20
|
rescue LoadError
|
20
21
|
end
|
21
22
|
end.must_output "fog gem required to use cloud features.
|
@@ -24,13 +25,13 @@ Please \"gem install fog\".
|
|
24
25
|
end
|
25
26
|
|
26
27
|
it 'sets correct options and connects' do
|
27
|
-
connect_to_cloud
|
28
|
+
subject.connect_to_cloud
|
28
29
|
$conf.cloud.connection.must_be_kind_of Fog::Compute::AWS::Mock
|
29
30
|
end
|
30
31
|
|
31
32
|
it 'creates a server' do
|
32
|
-
connect_to_cloud
|
33
|
-
create_server
|
33
|
+
subject.connect_to_cloud
|
34
|
+
subject.create_server
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
include Machines::Questions
|
3
|
+
describe Commandline do
|
4
|
+
|
5
|
+
subject { Commandline.new }
|
7
6
|
|
8
7
|
before(:each) do
|
8
|
+
subject
|
9
|
+
Commandline.stubs(:new).returns subject
|
9
10
|
$conf.log_only = false
|
10
11
|
File.open('config.yml', 'w') {|f| f.puts "timezone: GB" }
|
11
12
|
FileUtils.mkdir_p 'log'
|
@@ -13,7 +14,7 @@ describe Machines::Commandline do
|
|
13
14
|
|
14
15
|
describe 'build' do
|
15
16
|
before(:each) do
|
16
|
-
stubs(:init)
|
17
|
+
subject.stubs(:init)
|
17
18
|
FileUtils.touch('Machinesfile')
|
18
19
|
$conf.machine = AppConf.new
|
19
20
|
$conf.machine.address = 'target'
|
@@ -25,18 +26,18 @@ describe Machines::Commandline do
|
|
25
26
|
end
|
26
27
|
|
27
28
|
it 'displays syntax when no machine name specified' do
|
28
|
-
lambda { build [] }.must_output
|
29
|
+
lambda { subject.build [] }.must_output Help.new.syntax
|
29
30
|
end
|
30
31
|
|
31
32
|
it 'sets machine_name' do
|
32
|
-
build ['machine']
|
33
|
+
subject.build ['machine']
|
33
34
|
$conf.machine_name.must_equal 'machine'
|
34
35
|
end
|
35
36
|
|
36
37
|
it 'starts an SCP session using password authentication' do
|
37
38
|
options = {paranoid: false, password: 'userpass'}
|
38
39
|
Net::SSH.expects(:start).with('target', 'username', options).returns @ssh_stub
|
39
|
-
build ['machine']
|
40
|
+
subject.build ['machine']
|
40
41
|
end
|
41
42
|
|
42
43
|
it 'starts an SCP session using key based authentication' do
|
@@ -46,52 +47,53 @@ describe Machines::Commandline do
|
|
46
47
|
options = {paranoid: false, keys: ['path/to/private_key']}
|
47
48
|
Net::SSH.expects(:start).with('target', 'ubuntu', options).returns @ssh_stub
|
48
49
|
|
49
|
-
build ['machine']
|
50
|
+
subject.build ['machine']
|
50
51
|
end
|
51
52
|
|
52
53
|
it 'runs each command' do
|
53
|
-
mock_command = mock '
|
54
|
+
mock_command = mock 'Command'
|
54
55
|
$conf.commands = [mock_command]
|
55
56
|
|
56
57
|
mock_command.expects(:run)
|
57
58
|
|
58
|
-
build ['machine']
|
59
|
+
subject.build ['machine']
|
59
60
|
end
|
60
61
|
|
61
62
|
it 'flushes log file after running command' do
|
62
63
|
$conf.log_only = false
|
63
|
-
command_stub = stub('
|
64
|
+
command_stub = stub('command', :run => nil)
|
64
65
|
$conf.commands = [command_stub]
|
65
66
|
|
66
|
-
|
67
|
-
build ['machine']
|
67
|
+
Command.file.expects(:flush)
|
68
|
+
subject.build ['machine']
|
68
69
|
end
|
69
70
|
|
70
71
|
it 'only run specified tasks' do
|
71
|
-
command_will_run =
|
72
|
-
command_also_run =
|
73
|
-
command_wont_run =
|
74
|
-
$conf.tasks = {
|
75
|
-
:task1 => {:block =>
|
76
|
-
:task2 => {:block =>
|
72
|
+
command_will_run = Command.new 'will run', ''
|
73
|
+
command_also_run = Command.new 'also run', ''
|
74
|
+
command_wont_run = Command.new 'wont run', ''
|
75
|
+
$conf.tasks = {
|
76
|
+
:task1 => {:block => lambda { $conf.commands << command_will_run }},
|
77
|
+
:task2 => {:block => lambda { $conf.commands << command_also_run }},
|
78
|
+
:task3 => {:block => lambda { $conf.commands << command_wont_run }}
|
77
79
|
}
|
78
80
|
|
79
|
-
build ['machine', 'task1', 'task2']
|
81
|
+
subject.build ['machine', 'task1', 'task2']
|
80
82
|
|
81
83
|
$conf.commands.must_equal [command_will_run, command_also_run]
|
82
84
|
end
|
83
85
|
|
84
86
|
it 'logs instead of SSHing and running commands' do
|
85
87
|
Net::SCP.expects(:start).never
|
86
|
-
$conf.commands = [mock('
|
88
|
+
$conf.commands = [mock('command')]
|
87
89
|
$conf.commands.first.expects(:run)
|
88
90
|
$conf.log_only = true
|
89
|
-
build ['machine']
|
91
|
+
subject.build ['machine']
|
90
92
|
end
|
91
93
|
|
92
94
|
describe 'interrupts' do
|
93
95
|
before(:each) do
|
94
|
-
mock_command = mock '
|
96
|
+
mock_command = mock 'command'
|
95
97
|
$conf.commands = [mock_command]
|
96
98
|
|
97
99
|
mock_command.stubs(:run)
|
@@ -99,14 +101,13 @@ describe Machines::Commandline do
|
|
99
101
|
end
|
100
102
|
|
101
103
|
it 'handles CTRL+C and calls handler' do
|
102
|
-
expects(:prepare_to_exit)
|
104
|
+
subject.expects(:prepare_to_exit)
|
103
105
|
Kernel.expects(:trap).with('INT').yields
|
104
|
-
build ['machine']
|
106
|
+
subject.build ['machine']
|
105
107
|
end
|
106
108
|
|
107
|
-
|
108
109
|
it 'sets exit flag and displays message' do
|
109
|
-
prepare_to_exit
|
110
|
+
subject.send :prepare_to_exit
|
110
111
|
$exit_requested.must_equal true
|
111
112
|
message = "\nEXITING after current command completes...\n"
|
112
113
|
$console.next.must_equal colored(message, :warning)
|
@@ -114,15 +115,15 @@ describe Machines::Commandline do
|
|
114
115
|
|
115
116
|
it 'second request to exit exits immediately' do
|
116
117
|
$exit_requested = true
|
117
|
-
expects(:exit)
|
118
|
-
prepare_to_exit
|
118
|
+
subject.expects(:exit)
|
119
|
+
subject.send :prepare_to_exit
|
119
120
|
end
|
120
121
|
|
121
122
|
it 'exits when exit requested' do
|
122
123
|
$exit_requested = true
|
123
|
-
expects(:exit)
|
124
|
+
subject.expects(:exit)
|
124
125
|
|
125
|
-
build ['machine']
|
126
|
+
subject.build ['machine']
|
126
127
|
end
|
127
128
|
end
|
128
129
|
end
|
@@ -130,54 +131,54 @@ describe Machines::Commandline do
|
|
130
131
|
describe 'dryrun' do
|
131
132
|
it 'asks build to only log commands' do
|
132
133
|
options = []
|
133
|
-
expects(:build).with options
|
134
|
-
dryrun options
|
134
|
+
subject.expects(:build).with options
|
135
|
+
subject.dryrun options
|
135
136
|
$conf.log_only.must_equal true
|
136
137
|
end
|
137
138
|
|
138
139
|
it 'passes tasks to build' do
|
139
140
|
options = ['machine', 'task']
|
140
|
-
expects(:build).with options
|
141
|
-
dryrun options
|
141
|
+
subject.expects(:build).with options
|
142
|
+
subject.dryrun options
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
145
146
|
describe 'execute' do
|
146
147
|
it 'calls specified action' do
|
147
|
-
|
148
|
-
expects action
|
149
|
-
execute [action]
|
148
|
+
Help.new.actions.reject{|a| a == 'new'}.each do |action|
|
149
|
+
subject.expects action
|
150
|
+
Commandline.execute [action]
|
150
151
|
end
|
151
152
|
end
|
152
153
|
|
153
154
|
it 'calls generate with folder' do
|
154
|
-
expects(:generate).with(['dir'])
|
155
|
-
execute ['new', 'dir']
|
155
|
+
subject.expects(:generate).with(['dir'])
|
156
|
+
Commandline.execute ['new', 'dir']
|
156
157
|
end
|
157
158
|
|
158
159
|
it 'calls generate without folder' do
|
159
|
-
expects(:generate).with([])
|
160
|
-
execute ['new']
|
160
|
+
subject.expects(:generate).with([])
|
161
|
+
Commandline.execute ['new']
|
161
162
|
end
|
162
163
|
|
163
164
|
it 'calls help when no matching command' do
|
164
|
-
lambda { execute ['anything'] }.must_output
|
165
|
+
lambda { Commandline.execute ['anything'] }.must_output Help.new.syntax
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
168
169
|
describe 'generate' do
|
169
170
|
it 'copies the template within ./' do
|
170
|
-
expects(:ask).with("Overwrite './' (y/n)? ").returns 'y'
|
171
|
+
subject.expects(:ask).with("Overwrite './' (y/n)? ").returns 'y'
|
171
172
|
FileUtils.expects(:cp_r).with("#{$conf.application_dir}/template/.", './')
|
172
173
|
FileUtils.expects(:mkdir_p).with('./packages')
|
173
|
-
generate []
|
174
|
+
subject.generate []
|
174
175
|
end
|
175
176
|
|
176
177
|
it 'copies the template within dir' do
|
177
178
|
FileUtils.expects(:cp_r).with("#{$conf.application_dir}/template/.", 'dir')
|
178
179
|
FileUtils.expects(:mkdir_p).with(File.join('dir', 'packages'))
|
179
|
-
expects(:say).with('Project created at dir/')
|
180
|
-
generate ['dir']
|
180
|
+
subject.expects(:say).with('Project created at dir/')
|
181
|
+
subject.generate ['dir']
|
181
182
|
end
|
182
183
|
|
183
184
|
describe 'when folder exists' do
|
@@ -186,17 +187,17 @@ describe Machines::Commandline do
|
|
186
187
|
end
|
187
188
|
|
188
189
|
it 'is overwritten after user confirmation' do
|
189
|
-
expects(:ask).with("Overwrite 'dir' (y/n)? ").returns 'y'
|
190
|
+
subject.expects(:ask).with("Overwrite 'dir' (y/n)? ").returns 'y'
|
190
191
|
FileUtils.expects(:cp_r).with("#{$conf.application_dir}/template/.", 'dir')
|
191
192
|
FileUtils.expects(:mkdir_p).with(File.join('dir', 'packages'))
|
192
|
-
generate ['dir']
|
193
|
+
subject.generate ['dir']
|
193
194
|
end
|
194
195
|
|
195
196
|
it 'generation is aborted at user request' do
|
196
|
-
expects(:ask).with("Overwrite 'dir' (y/n)? ").returns 'n'
|
197
|
+
subject.expects(:ask).with("Overwrite 'dir' (y/n)? ").returns 'n'
|
197
198
|
FileUtils.expects(:cp_r).never
|
198
199
|
FileUtils.expects(:mkdir_p).never
|
199
|
-
generate ['dir']
|
200
|
+
subject.generate ['dir']
|
200
201
|
end
|
201
202
|
end
|
202
203
|
end
|
@@ -205,54 +206,32 @@ describe Machines::Commandline do
|
|
205
206
|
it 'htpasswd is generated and saved' do
|
206
207
|
$conf.webserver = 'server'
|
207
208
|
$input.string = "user\npass\npass\n"
|
208
|
-
htpasswd nil
|
209
|
+
subject.htpasswd nil
|
209
210
|
File.read('server/htpasswd').must_match /user:.{13}/
|
210
211
|
end
|
211
212
|
end
|
212
213
|
|
213
214
|
describe 'init' do
|
214
215
|
it 'initializes some $conf settings and loads configs' do
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
init
|
216
|
+
Command.file = nil
|
217
|
+
Command.console = nil
|
218
|
+
Command.debug = nil
|
219
|
+
subject.init
|
219
220
|
$conf.passwords.must_equal []
|
220
221
|
$conf.commands.must_equal []
|
221
222
|
$conf.tasks.must_equal({})
|
222
223
|
$conf.timezone.must_equal 'GB'
|
223
224
|
File.exists?('log/output.log').must_equal true
|
224
|
-
|
225
|
-
|
226
|
-
|
225
|
+
Command.file.must_be_instance_of Machines::Logger
|
226
|
+
Command.console.must_be_instance_of Machines::Logger
|
227
|
+
Command.debug.must_be_instance_of Machines::Logger
|
227
228
|
end
|
228
229
|
end
|
229
230
|
|
230
231
|
describe 'list' do
|
231
232
|
it 'lists machines' do
|
232
233
|
File.open('machines.yml', 'w') {|f| f.puts({'machines' => {'machine_1' => {}, 'machine_2' => {}}}.to_yaml) }
|
233
|
-
lambda { list nil }.must_output "Machines from machines.yml:\n machine_1\n machine_2\n"
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe 'load_machinesfile' do
|
238
|
-
it 'raises LoadError with custom message when no Machinesfile' do
|
239
|
-
File.expects(:read).with("Machinesfile").raises LoadError.new('Machinesfile not found')
|
240
|
-
|
241
|
-
begin
|
242
|
-
load_machinesfile
|
243
|
-
rescue LoadError => e
|
244
|
-
e.message.must_equal 'Machinesfile does not exist. Use `machines new <DIR>` to create a template.'
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
it 'raises normal LoadError on other files' do
|
249
|
-
File.expects(:read).with("Machinesfile").raises LoadError
|
250
|
-
|
251
|
-
begin
|
252
|
-
load_machinesfile
|
253
|
-
rescue LoadError => e
|
254
|
-
e.message.must_equal 'LoadError'
|
255
|
-
end
|
234
|
+
lambda { subject.list nil }.must_output "Machines from machines.yml:\n machine_1\n machine_2\n"
|
256
235
|
end
|
257
236
|
end
|
258
237
|
|
@@ -264,7 +243,7 @@ describe Machines::Commandline do
|
|
264
243
|
end
|
265
244
|
|
266
245
|
it 'copies package to project folder' do
|
267
|
-
override ['base']
|
246
|
+
subject.override ['base']
|
268
247
|
File.exists?('packages/base.rb').must_equal true
|
269
248
|
end
|
270
249
|
|
@@ -275,14 +254,14 @@ describe Machines::Commandline do
|
|
275
254
|
|
276
255
|
it 'terminates when user answer no' do
|
277
256
|
$input.string = "n\n"
|
278
|
-
lambda { override ['base'] }.must_output 'Project package already exists. Overwrite? (y/n)
|
257
|
+
lambda { subject.override ['base'] }.must_output 'Project package already exists. Overwrite? (y/n)
|
279
258
|
Aborted.
|
280
259
|
'
|
281
260
|
end
|
282
261
|
|
283
262
|
it 'overwrites project package with default package' do
|
284
263
|
$input.string = "y\n"
|
285
|
-
lambda { override ['base'] }.must_output 'Project package already exists. Overwrite? (y/n)
|
264
|
+
lambda { subject.override ['base'] }.must_output 'Project package already exists. Overwrite? (y/n)
|
286
265
|
Package copied to packages/base.rb
|
287
266
|
'
|
288
267
|
end
|
@@ -295,7 +274,7 @@ Package copied to packages/base.rb
|
|
295
274
|
FileUtils.mkdir_p 'packages'
|
296
275
|
FileUtils.touch File.join($conf.application_dir, 'packages', 'base.rb')
|
297
276
|
FileUtils.touch File.join('packages', 'apps.rb')
|
298
|
-
lambda { packages nil }.must_output 'Default packages
|
277
|
+
lambda { subject.packages nil }.must_output 'Default packages
|
299
278
|
* base
|
300
279
|
Project packages
|
301
280
|
* apps
|
@@ -305,14 +284,14 @@ Project packages
|
|
305
284
|
|
306
285
|
describe 'tasks' do
|
307
286
|
it 'displays a list of tasks' do
|
308
|
-
expects(:init)
|
309
|
-
expects(:
|
287
|
+
subject.expects(:init)
|
288
|
+
Core.any_instance.expects(:package).with 'Machinesfile'
|
310
289
|
$conf.tasks = {
|
311
290
|
:task1 => {:description => 'description 1'},
|
312
291
|
:task2 => {:description => 'description 2'},
|
313
292
|
:task3 => {:description => 'description 3'}
|
314
293
|
}
|
315
|
-
lambda { tasks ['machine'] }.must_output 'Tasks
|
294
|
+
lambda { subject.tasks ['machine'] }.must_output 'Tasks
|
316
295
|
task1 description 1
|
317
296
|
task2 description 2
|
318
297
|
task3 description 3
|