jisota 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +21 -0
- data/README.md +106 -2
- data/Rakefile +10 -0
- data/jisota.gemspec +1 -0
- data/lib/jisota.rb +4 -2
- data/lib/jisota/collection.rb +2 -4
- data/lib/jisota/command_script.rb +3 -2
- data/lib/jisota/composite_script.rb +2 -2
- data/lib/jisota/configuration.rb +3 -3
- data/lib/jisota/dsl_base.rb +12 -0
- data/lib/jisota/file_script.rb +107 -9
- data/lib/jisota/nil_output.rb +14 -0
- data/lib/jisota/{logger.rb → output.rb} +16 -35
- data/lib/jisota/package.rb +2 -2
- data/lib/jisota/package_script.rb +28 -20
- data/lib/jisota/packages/gem_install.rb +17 -0
- data/lib/jisota/packages/nginx_passenger.rb +34 -0
- data/lib/jisota/packages/ruby.rb +2 -2
- data/lib/jisota/param_parser.rb +30 -19
- data/lib/jisota/provisioner.rb +7 -3
- data/lib/jisota/script_block.rb +13 -14
- data/lib/jisota/script_context.rb +24 -0
- data/lib/jisota/server.rb +2 -1
- data/lib/jisota/ssh_engine.rb +6 -2
- data/lib/jisota/ssh_session.rb +10 -15
- data/lib/jisota/version.rb +1 -1
- data/package_files/nginx_passenger/nginx_service +65 -0
- data/spec/acceptance/ruby_passenger_nginx_spec.rb +24 -0
- data/spec/acceptance/simple_script_spec.rb +8 -24
- data/spec/acceptance/upload_blocks_spec.rb +34 -0
- data/spec/lib/jisota/collection_spec.rb +10 -0
- data/spec/lib/jisota/command_script_spec.rb +4 -3
- data/spec/lib/jisota/composite_script_spec.rb +8 -6
- data/spec/lib/jisota/configuration_spec.rb +1 -3
- data/spec/lib/jisota/dsl_base_spec.rb +37 -0
- data/spec/lib/jisota/file_script_spec.rb +63 -8
- data/spec/lib/jisota/output_spec.rb +84 -0
- data/spec/lib/jisota/package_script_spec.rb +20 -8
- data/spec/lib/jisota/package_spec.rb +2 -6
- data/spec/lib/jisota/packages/apt_spec.rb +7 -4
- data/spec/lib/jisota/packages/gem_install_spec.rb +18 -0
- data/spec/lib/jisota/packages/nginx_passenger_spec.rb +17 -0
- data/spec/lib/jisota/packages/ruby_spec.rb +6 -3
- data/spec/lib/jisota/param_parser_spec.rb +105 -0
- data/spec/lib/jisota/provisioner_spec.rb +30 -0
- data/spec/lib/jisota/role_spec.rb +1 -3
- data/spec/lib/jisota/script_block_spec.rb +7 -4
- data/spec/lib/jisota/ssh_engine_spec.rb +26 -0
- data/spec/lib/jisota/ssh_session_spec.rb +53 -0
- data/spec/spec_helper.rb +11 -1
- data/spec/support/acceptance_helpers.rb +45 -0
- data/spec/test_files/nginx_default.conf +121 -0
- data/spec/vagrant/Vagrantfile +118 -0
- data/spec/vagrant/ssh_key +27 -0
- metadata +55 -7
- data/lib/jisota/upload_file.rb +0 -3
- data/spec/lib/jisota/logger_spec.rb +0 -34
@@ -4,7 +4,7 @@ module Jisota
|
|
4
4
|
#
|
5
5
|
# Will default to use STDOUT and STDERR, but that can be overwritten in the
|
6
6
|
# initializer
|
7
|
-
class
|
7
|
+
class Output
|
8
8
|
attr_accessor :stdout, :stderr, :verbose, :prefix, :indent_level
|
9
9
|
|
10
10
|
def initialize(options = {})
|
@@ -15,60 +15,41 @@ module Jisota
|
|
15
15
|
@indent_level = 0
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
prefixed_message "Uploading #{from} -> #{to}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def package(package_script)
|
27
|
-
prefixed_message "Package #{package_script}"
|
28
|
-
end
|
29
|
-
|
30
|
-
def package_cancelled_by_verify(package_script)
|
31
|
-
prefixed_message "Package #{package_script} already installed"
|
32
|
-
end
|
33
|
-
|
34
|
-
def prefixed_message(message)
|
35
|
-
stdout.write(create_message(message, true, true))
|
18
|
+
def system_message(message, &block)
|
19
|
+
result = ["", prefix, " " * indent_level, message, "\n"].join
|
20
|
+
stdout.write(result)
|
21
|
+
stdout.flush
|
22
|
+
indent(&block) if block_given?
|
36
23
|
end
|
37
24
|
|
38
25
|
def info(message)
|
39
26
|
stdout.write(message) if verbose
|
27
|
+
stdout.flush
|
40
28
|
end
|
41
29
|
|
42
30
|
def warn(message)
|
43
31
|
stderr.write(message) if verbose
|
32
|
+
stderr.flush
|
44
33
|
end
|
45
34
|
|
46
35
|
def error(message)
|
47
36
|
stderr.write(message)
|
37
|
+
stderr.flush
|
48
38
|
end
|
49
39
|
|
50
40
|
def indent
|
51
41
|
self.indent_level += 1
|
42
|
+
if block_given?
|
43
|
+
begin
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
outdent
|
47
|
+
end
|
48
|
+
end
|
52
49
|
end
|
53
50
|
|
54
51
|
def outdent
|
55
52
|
self.indent_level -= 1
|
56
53
|
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def create_message(message, newline, use_prefix)
|
61
|
-
result = ""
|
62
|
-
if use_prefix
|
63
|
-
result << prefix
|
64
|
-
else
|
65
|
-
result << " " * prefix.size
|
66
|
-
end
|
67
|
-
result << " " * indent_level
|
68
|
-
result << message
|
69
|
-
result << "\n" if newline
|
70
|
-
result
|
71
|
-
end
|
72
|
-
|
73
54
|
end
|
74
55
|
end
|
data/lib/jisota/package.rb
CHANGED
@@ -5,12 +5,12 @@ module Jisota
|
|
5
5
|
def initialize(name = nil, &block)
|
6
6
|
@params = []
|
7
7
|
@name = name
|
8
|
-
DSL.new(self).
|
8
|
+
DSL.new(self).evaluate(&block) if block_given?
|
9
9
|
end
|
10
10
|
|
11
11
|
alias_method :key, :name
|
12
12
|
|
13
|
-
class DSL
|
13
|
+
class DSL < DSLBase
|
14
14
|
def initialize(target)
|
15
15
|
@target = target
|
16
16
|
end
|
@@ -8,47 +8,55 @@ module Jisota
|
|
8
8
|
# If the package has a `verify_block`, that will be executed first. If the
|
9
9
|
# result of verify is success, the `run_block` will not be executed.
|
10
10
|
class PackageScript
|
11
|
-
attr_accessor :package, :args
|
11
|
+
attr_accessor :package, :args
|
12
12
|
|
13
|
-
def initialize(package, args = []
|
13
|
+
def initialize(package, args = [])
|
14
14
|
@package = package
|
15
15
|
@args = args
|
16
|
-
@packages = packages
|
17
16
|
end
|
18
17
|
|
19
|
-
def execute(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
def execute(context)
|
19
|
+
context.param_scope(parse_params) do
|
20
|
+
context.logger.system_message("Package #{self}") do
|
21
|
+
execute_verify_and_run(context)
|
22
|
+
end
|
23
|
+
end
|
25
24
|
end
|
26
25
|
|
27
26
|
def to_s
|
28
|
-
|
27
|
+
result = ""
|
28
|
+
result << package.name.to_s
|
29
|
+
if args.any?
|
30
|
+
result << " "
|
31
|
+
result << args.map(&:inspect).join(", ")
|
32
|
+
end
|
33
|
+
result
|
29
34
|
end
|
30
35
|
|
31
36
|
private
|
32
37
|
|
33
|
-
def
|
34
|
-
|
38
|
+
def parse_params
|
39
|
+
ParamParser.new(package.params, args).parse
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute_verify_and_run(context)
|
35
43
|
if package.verify_block
|
36
|
-
verify_script = package.verify_block.evaluate(
|
37
|
-
result = verify_script.execute(
|
44
|
+
verify_script = package.verify_block.evaluate(context)
|
45
|
+
result = verify_script.execute(context)
|
38
46
|
if result
|
39
|
-
logger.
|
47
|
+
context.logger.system_message("Package #{self} already installed")
|
40
48
|
true
|
41
49
|
else
|
42
|
-
execute_run(
|
50
|
+
execute_run(context)
|
43
51
|
end
|
44
52
|
else
|
45
|
-
execute_run(
|
53
|
+
execute_run(context)
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
49
|
-
def execute_run(
|
50
|
-
run_script = package.run_block.evaluate(
|
51
|
-
run_script.execute(
|
57
|
+
def execute_run(context)
|
58
|
+
run_script = package.run_block.evaluate(context)
|
59
|
+
run_script.execute(context)
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'jisota'
|
2
|
+
|
3
|
+
Jisota.global_config do
|
4
|
+
package :gem_install do
|
5
|
+
description "Installs a gem"
|
6
|
+
param :gem_name, required: true
|
7
|
+
param :sudo, default: true
|
8
|
+
|
9
|
+
run do
|
10
|
+
cmd "#{sudo ? "sudo " : ""}gem install #{gem_name} --no-document"
|
11
|
+
end
|
12
|
+
|
13
|
+
verify do
|
14
|
+
cmd "#{sudo ? "sudo " : ""}gem list #{gem_name} --installed"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'jisota'
|
2
|
+
|
3
|
+
Jisota.global_config do
|
4
|
+
package :nginx_passenger do
|
5
|
+
description "Install nginx with passenger module"
|
6
|
+
param :config_file, required: true
|
7
|
+
|
8
|
+
run do
|
9
|
+
gem_install :passenger
|
10
|
+
apt "libcurl4-openssl-dev"
|
11
|
+
nginx_passenger_install
|
12
|
+
|
13
|
+
upload from: config_file, to: '/opt/nginx/conf/nginx.conf' do
|
14
|
+
update { cmd "sudo service nginx restart" }
|
15
|
+
end
|
16
|
+
|
17
|
+
upload from: "package_files/nginx_passenger/nginx_service", to: "/etc/init.d/nginx" do
|
18
|
+
create { cmd 'sudo update-rc.d nginx defaults 99' }
|
19
|
+
end
|
20
|
+
|
21
|
+
nginx_passenger_start
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
package :nginx_passenger_install do
|
26
|
+
run { cmd 'sudo passenger-install-nginx-module --auto --auto-download --prefix=/opt/nginx' }
|
27
|
+
verify { cmd 'which /opt/nginx/sbin/nginx' }
|
28
|
+
end
|
29
|
+
|
30
|
+
package :nginx_passenger_start do
|
31
|
+
run { cmd "sudo service nginx start" }
|
32
|
+
verify { cmd "ps -C nginx" }
|
33
|
+
end
|
34
|
+
end
|
data/lib/jisota/packages/ruby.rb
CHANGED
@@ -9,7 +9,7 @@ Jisota.global_config do
|
|
9
9
|
run do
|
10
10
|
minor_version = version.match(/\d+\.\d+/)[0]
|
11
11
|
|
12
|
-
apt *%w(libffi-dev libssl-dev zlib1g-dev libreadline-dev)
|
12
|
+
apt *%w(libffi-dev libssl-dev zlib1g-dev libreadline-dev build-essential)
|
13
13
|
cmd %Q{
|
14
14
|
mkdir -p #{tmp_dir} &&
|
15
15
|
cd #{tmp_dir} &&
|
@@ -18,7 +18,7 @@ Jisota.global_config do
|
|
18
18
|
cd ruby-#{version} &&
|
19
19
|
./configure &&
|
20
20
|
make &&
|
21
|
-
sudo make install
|
21
|
+
sudo make install
|
22
22
|
}
|
23
23
|
end
|
24
24
|
|
data/lib/jisota/param_parser.rb
CHANGED
@@ -3,17 +3,17 @@ module Jisota
|
|
3
3
|
attr_reader :params, :args
|
4
4
|
|
5
5
|
def initialize(params, args)
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@args = args.dup
|
6
|
+
@params = params
|
7
|
+
@args = args
|
9
8
|
end
|
10
9
|
|
11
10
|
def parse
|
11
|
+
params_work_list = params.dup
|
12
12
|
Hash.new.tap do |result|
|
13
13
|
init_splat_params(result)
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
add_unnamed_args(result, params_work_list)
|
15
|
+
add_named_args(result)
|
16
|
+
handle_remaining_params(result, params_work_list)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -25,12 +25,11 @@ module Jisota
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def add_unnamed_args(result, params_work_list)
|
29
29
|
param = nil
|
30
|
-
|
31
|
-
param =
|
32
|
-
arg
|
33
|
-
raise ParameterError, "No parameter for implicit argument #{arg}" unless param
|
30
|
+
unnamed_args.each do |arg|
|
31
|
+
param = params_work_list.shift unless param && param.splat?
|
32
|
+
raise ParameterError, "No parameter for unnamed argument #{arg}" unless param
|
34
33
|
if param.splat?
|
35
34
|
result[param.name] << arg
|
36
35
|
else
|
@@ -39,25 +38,37 @@ module Jisota
|
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
args.first.each do |key, value|
|
46
|
-
param = @original_params.select { |p| p.name == key }.first
|
41
|
+
def add_named_args(result)
|
42
|
+
named_args.each do |key, value|
|
43
|
+
param = params.select { |p| p.name == key }.first
|
47
44
|
raise ParameterError, "No parameter with name #{key.inspect}" unless param
|
48
45
|
if result.has_key?(key)
|
49
46
|
if param.splat?
|
50
47
|
raise ParameterError, "Splat parameter #{key.inspect} only accepts unnamed arguments"
|
51
48
|
else
|
52
|
-
raise ParameterError, "Parameter #{key.inspect} already set with an
|
49
|
+
raise ParameterError, "Parameter #{key.inspect} already set with an unnamed argument"
|
53
50
|
end
|
54
51
|
end
|
55
52
|
result[key] = value
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
59
|
-
def
|
60
|
-
|
56
|
+
def unnamed_args
|
57
|
+
args.dup.tap do |result|
|
58
|
+
result.pop if named_args?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def named_args
|
63
|
+
named_args? ? args.last : {}
|
64
|
+
end
|
65
|
+
|
66
|
+
def named_args?
|
67
|
+
args.last.is_a?(Hash)
|
68
|
+
end
|
69
|
+
|
70
|
+
def handle_remaining_params(result, params_work_list)
|
71
|
+
params_work_list.each do |param|
|
61
72
|
unless result.has_key?(param.name)
|
62
73
|
if param.required? && !param.default?
|
63
74
|
raise ParameterError, "Parameter #{param.name.inspect} is required"
|
data/lib/jisota/provisioner.rb
CHANGED
@@ -12,11 +12,15 @@ module Jisota
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def run_server(server, ssh, roles, packages, logger)
|
15
|
-
|
15
|
+
ssh_options = { user: server.user, host: server.host }
|
16
|
+
ssh_options[:keys] = [server.key] if server.key
|
17
|
+
|
18
|
+
ssh.start(ssh_options) do |ssh_session|
|
16
19
|
server.roles.each do |role_name|
|
17
20
|
role = roles[role_name]
|
18
|
-
|
19
|
-
script.
|
21
|
+
context = ScriptContext.new(ssh_session: ssh_session, logger: logger, packages: packages)
|
22
|
+
script = role.script_block.evaluate(context)
|
23
|
+
script.execute(context)
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
data/lib/jisota/script_block.rb
CHANGED
@@ -15,26 +15,25 @@ module Jisota
|
|
15
15
|
@block = block
|
16
16
|
end
|
17
17
|
|
18
|
-
def evaluate(
|
18
|
+
def evaluate(context = ScriptContext.new)
|
19
19
|
CompositeScript.new.tap do |script|
|
20
|
-
dsl = DSL.new(script,
|
21
|
-
dsl.
|
20
|
+
dsl = DSL.new(script, context)
|
21
|
+
dsl.evaluate(&block)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class DSL
|
26
|
-
def initialize(script,
|
25
|
+
class DSL < DSLBase
|
26
|
+
def initialize(script, context)
|
27
27
|
@script = script
|
28
|
-
@
|
29
|
-
@packages = packages
|
28
|
+
@context = context
|
30
29
|
end
|
31
30
|
|
32
31
|
def cmd(command)
|
33
32
|
@script.scripts << CommandScript.new(command)
|
34
33
|
end
|
35
34
|
|
36
|
-
def upload(
|
37
|
-
@script.scripts << FileScript.new(
|
35
|
+
def upload(**options, &block)
|
36
|
+
@script.scripts << FileScript.new(**options, &block)
|
38
37
|
end
|
39
38
|
|
40
39
|
def method_missing(method, *args, &block)
|
@@ -48,17 +47,17 @@ module Jisota
|
|
48
47
|
private
|
49
48
|
|
50
49
|
def has_argument?(name)
|
51
|
-
@
|
50
|
+
@context.params.has_key?(name)
|
52
51
|
end
|
53
52
|
|
54
53
|
def get_argument(name)
|
55
|
-
@
|
54
|
+
@context.params.fetch(name)
|
56
55
|
end
|
57
56
|
|
58
57
|
def add_package_script(name, args)
|
59
|
-
if @packages.has_key?(name)
|
60
|
-
package = @packages[name]
|
61
|
-
@script.scripts << PackageScript.new(package, args
|
58
|
+
if @context.packages.has_key?(name)
|
59
|
+
package = @context.packages[name]
|
60
|
+
@script.scripts << PackageScript.new(package, args)
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Jisota
|
2
|
+
class ScriptContext
|
3
|
+
attr_accessor :ssh_session, :logger, :params, :packages
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@ssh_session = options.fetch(:ssh_session) { nil }
|
7
|
+
@logger = options.fetch(:logger) { NilOutput.new }
|
8
|
+
@params = options.fetch(:params) { Hash.new }
|
9
|
+
@packages = options.fetch(:packages) { Collection.new }
|
10
|
+
end
|
11
|
+
|
12
|
+
def command(cmd)
|
13
|
+
ssh_session.command(cmd, logger)
|
14
|
+
end
|
15
|
+
|
16
|
+
def param_scope(scope_params)
|
17
|
+
old_params = params
|
18
|
+
self.params = scope_params
|
19
|
+
result = yield if block_given?
|
20
|
+
self.params = old_params
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|