jisota 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/CHANGELOG.md +21 -0
  5. data/README.md +106 -2
  6. data/Rakefile +10 -0
  7. data/jisota.gemspec +1 -0
  8. data/lib/jisota.rb +4 -2
  9. data/lib/jisota/collection.rb +2 -4
  10. data/lib/jisota/command_script.rb +3 -2
  11. data/lib/jisota/composite_script.rb +2 -2
  12. data/lib/jisota/configuration.rb +3 -3
  13. data/lib/jisota/dsl_base.rb +12 -0
  14. data/lib/jisota/file_script.rb +107 -9
  15. data/lib/jisota/nil_output.rb +14 -0
  16. data/lib/jisota/{logger.rb → output.rb} +16 -35
  17. data/lib/jisota/package.rb +2 -2
  18. data/lib/jisota/package_script.rb +28 -20
  19. data/lib/jisota/packages/gem_install.rb +17 -0
  20. data/lib/jisota/packages/nginx_passenger.rb +34 -0
  21. data/lib/jisota/packages/ruby.rb +2 -2
  22. data/lib/jisota/param_parser.rb +30 -19
  23. data/lib/jisota/provisioner.rb +7 -3
  24. data/lib/jisota/script_block.rb +13 -14
  25. data/lib/jisota/script_context.rb +24 -0
  26. data/lib/jisota/server.rb +2 -1
  27. data/lib/jisota/ssh_engine.rb +6 -2
  28. data/lib/jisota/ssh_session.rb +10 -15
  29. data/lib/jisota/version.rb +1 -1
  30. data/package_files/nginx_passenger/nginx_service +65 -0
  31. data/spec/acceptance/ruby_passenger_nginx_spec.rb +24 -0
  32. data/spec/acceptance/simple_script_spec.rb +8 -24
  33. data/spec/acceptance/upload_blocks_spec.rb +34 -0
  34. data/spec/lib/jisota/collection_spec.rb +10 -0
  35. data/spec/lib/jisota/command_script_spec.rb +4 -3
  36. data/spec/lib/jisota/composite_script_spec.rb +8 -6
  37. data/spec/lib/jisota/configuration_spec.rb +1 -3
  38. data/spec/lib/jisota/dsl_base_spec.rb +37 -0
  39. data/spec/lib/jisota/file_script_spec.rb +63 -8
  40. data/spec/lib/jisota/output_spec.rb +84 -0
  41. data/spec/lib/jisota/package_script_spec.rb +20 -8
  42. data/spec/lib/jisota/package_spec.rb +2 -6
  43. data/spec/lib/jisota/packages/apt_spec.rb +7 -4
  44. data/spec/lib/jisota/packages/gem_install_spec.rb +18 -0
  45. data/spec/lib/jisota/packages/nginx_passenger_spec.rb +17 -0
  46. data/spec/lib/jisota/packages/ruby_spec.rb +6 -3
  47. data/spec/lib/jisota/param_parser_spec.rb +105 -0
  48. data/spec/lib/jisota/provisioner_spec.rb +30 -0
  49. data/spec/lib/jisota/role_spec.rb +1 -3
  50. data/spec/lib/jisota/script_block_spec.rb +7 -4
  51. data/spec/lib/jisota/ssh_engine_spec.rb +26 -0
  52. data/spec/lib/jisota/ssh_session_spec.rb +53 -0
  53. data/spec/spec_helper.rb +11 -1
  54. data/spec/support/acceptance_helpers.rb +45 -0
  55. data/spec/test_files/nginx_default.conf +121 -0
  56. data/spec/vagrant/Vagrantfile +118 -0
  57. data/spec/vagrant/ssh_key +27 -0
  58. metadata +55 -7
  59. data/lib/jisota/upload_file.rb +0 -3
  60. data/spec/lib/jisota/logger_spec.rb +0 -34
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ module Jisota
4
+ describe Output do
5
+ let(:logger) { Output.new(stdout: stdout, stderr: stderr, verbose: verbose) }
6
+ let(:stdout) { instance_double(IO, write: nil, flush: nil) }
7
+ let(:stderr) { instance_double(IO, write: nil, flush: nil) }
8
+ let(:verbose) { true }
9
+
10
+ describe "initialization" do
11
+ it "initializes with options" do
12
+ logger = Output.new(stdout: :out, stderr: :err, verbose: false)
13
+ expect(logger.stdout).to eq(:out)
14
+ expect(logger.stderr).to eq(:err)
15
+ expect(logger.verbose).to be false
16
+ end
17
+ end
18
+
19
+ describe '#info' do
20
+ it "writes to stdout" do
21
+ logger.info("foo")
22
+ expect(stdout).to have_received(:write).with("foo")
23
+ end
24
+ end
25
+
26
+ describe "#error" do
27
+ it "writes to stderr" do
28
+ logger.error("foo")
29
+ expect(stderr).to have_received(:write).with("foo")
30
+ end
31
+ end
32
+
33
+ describe "#warn" do
34
+ context "verbose" do
35
+ let(:verbose) { true }
36
+ it "outputs" do
37
+ logger.warn("foo")
38
+ expect(stderr).to have_received(:write).with("foo")
39
+ end
40
+ end
41
+
42
+ context "not verbose" do
43
+ let(:verbose) { false }
44
+ it "outputs" do
45
+ logger.warn("foo")
46
+ expect(stderr).to_not have_received(:write).with("foo")
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "#system_message" do
52
+ it "outputs message" do
53
+ logger.system_message("foo")
54
+ expect(stdout).to have_received(:write).with("-----> foo\n")
55
+ end
56
+ end
57
+
58
+ describe "#indent" do
59
+ it "indents subsequent output" do
60
+ logger.indent
61
+ logger.system_message("foo")
62
+ expect(stdout).to have_received(:write).with("-----> foo\n")
63
+
64
+ logger.outdent
65
+ logger.system_message("foo")
66
+ expect(stdout).to have_received(:write).with("-----> foo\n")
67
+ end
68
+
69
+ context "with a block" do
70
+ it "indents logs inside block" do
71
+ result = logger.indent do
72
+ logger.system_message("foo")
73
+ 42
74
+ end
75
+ logger.system_message("bar")
76
+ expect(stdout).to have_received(:write).with("-----> foo\n")
77
+ expect(stdout).to have_received(:write).with("-----> bar\n")
78
+ expect(result).to eq(42)
79
+ end
80
+ end
81
+ end
82
+
83
+ end
84
+ end
@@ -3,17 +3,18 @@ require 'spec_helper'
3
3
  module Jisota
4
4
  describe PackageScript do
5
5
  describe "#execute" do
6
- let(:ssh_session) { instance_double(SSHSession, command: true) }
6
+ let(:ssh_session) { instance_double(SSHSession, command: 0) }
7
+ let(:context) { ScriptContext.new(ssh_session: ssh_session) }
7
8
 
8
9
  it "executes each script from the block" do
9
10
  package = Package.new do
10
11
  run { cmd "foo" }
11
12
  end
12
13
  package_script = PackageScript.new(package)
13
- result = package_script.execute(ssh_session)
14
+ result = package_script.execute(context)
14
15
 
15
16
  expect(result).to be true
16
- expect(ssh_session).to have_received(:command).with("foo", nil)
17
+ expect(ssh_session).to have_received(:command).with("foo", anything)
17
18
  end
18
19
 
19
20
  it "parses args" do
@@ -22,9 +23,9 @@ module Jisota
22
23
  run { cmd "foo #{bar}" }
23
24
  end
24
25
  package_script = PackageScript.new(package, ["baz"])
25
- package_script.execute(ssh_session)
26
+ package_script.execute(context)
26
27
 
27
- expect(ssh_session).to have_received(:command).with("foo baz", nil)
28
+ expect(ssh_session).to have_received(:command).with("foo baz", anything)
28
29
  end
29
30
 
30
31
  it "uses verify block" do
@@ -33,10 +34,21 @@ module Jisota
33
34
  verify { cmd "bar" }
34
35
  end
35
36
  package_script = PackageScript.new(package)
36
- package_script.execute(ssh_session)
37
+ package_script.execute(context)
37
38
 
38
- expect(ssh_session).to have_received(:command).with("bar", nil)
39
- expect(ssh_session).to_not have_received(:command).with("foo", nil)
39
+ expect(ssh_session).to have_received(:command).with("bar", anything)
40
+ expect(ssh_session).to_not have_received(:command).with("foo", anything)
41
+ end
42
+ end
43
+
44
+ describe "#to_s" do
45
+ it "outputs a nice representation of the script" do
46
+ package = Package.new(:nginx)
47
+
48
+ expect(PackageScript.new(package, []).to_s).to eq("nginx")
49
+ expect(PackageScript.new(package, ["foo"]).to_s).to eq('nginx "foo"')
50
+ expect(PackageScript.new(package, ["foo", 42]).to_s).to eq('nginx "foo", 42')
51
+ expect(PackageScript.new(package, [{ foo: 42 }]).to_s).to eq("nginx {:foo=>42}")
40
52
  end
41
53
  end
42
54
  end
@@ -53,12 +53,8 @@ module Jisota
53
53
  description "Does cool stuff"
54
54
  param :foo
55
55
  param :bar, default: 42
56
- run do
57
- cmd "touch #{foo}"
58
- end
59
- verify do
60
- cmd "[ -f foo ]"
61
- end
56
+ run { cmd "touch #{foo}" }
57
+ verify { cmd "[ -f foo ]" }
62
58
  end
63
59
 
64
60
  expect(package.name).to eq(:my_awesome_package)
@@ -2,14 +2,17 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  module Jisota
5
- describe "Ruby package" do
5
+ describe "Apt package" do
6
6
  it "is valid" do
7
7
  script_block = ScriptBlock.new do
8
8
  apt :curl
9
9
  end
10
- script = script_block.evaluate({}, Jisota.global_packages)
11
- ssh_session = instance_double(SSHSession, command: true, upload: true)
12
- expect { script.execute(ssh_session) }.to_not raise_exception
10
+ ssh_session = instance_double(SSHSession, upload: true)
11
+ allow(ssh_session).to receive(:command).and_return(false, true)
12
+ context = ScriptContext.new(ssh_session: ssh_session, packages: Jisota.global_packages)
13
+ script = script_block.evaluate(context)
14
+
15
+ expect { script.execute(context) }.to_not raise_exception
13
16
  end
14
17
  end
15
18
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module Jisota
4
+ describe "Gem-install package" do
5
+ it "is valid" do
6
+ script_block = ScriptBlock.new do
7
+ gem_install :foo
8
+ end
9
+ ssh_session = instance_double(SSHSession)
10
+ allow(ssh_session).to receive(:command).and_return(1, 0)
11
+ context = ScriptContext.new(ssh_session: ssh_session, packages: Jisota.global_packages)
12
+ script = script_block.evaluate(context)
13
+
14
+ expect { script.execute(context) }.to_not raise_exception
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ module Jisota
4
+ describe "Nginx Passenger package" do
5
+ it "is valid" do
6
+ script_block = ScriptBlock.new do
7
+ nginx_passenger config_file: "foo"
8
+ end
9
+ ssh_session = instance_double(SSHSession, upload: true, command: 0)
10
+ context = ScriptContext.new(ssh_session: ssh_session, packages: Jisota.global_packages)
11
+ script = script_block.evaluate(context)
12
+
13
+ expect { script.execute(context) }.to_not raise_exception
14
+ end
15
+ end
16
+ end
17
+
@@ -6,9 +6,12 @@ module Jisota
6
6
  script_block = ScriptBlock.new do
7
7
  ruby version: "2.1.1"
8
8
  end
9
- script = script_block.evaluate({}, Jisota.global_packages)
10
- ssh_session = instance_double(SSHSession, command: true, upload: true)
11
- expect { script.execute(ssh_session) }.to_not raise_exception
9
+ ssh_session = instance_double(SSHSession, upload: true)
10
+ allow(ssh_session).to receive(:command).and_return(false, true)
11
+ context = ScriptContext.new(ssh_session: ssh_session, packages: Jisota.global_packages)
12
+ script = script_block.evaluate(context)
13
+
14
+ expect { script.execute(context) }.to_not raise_exception
12
15
  end
13
16
  end
14
17
  end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jisota::ParamParser do
4
+ subject { parser.parse() }
5
+ let(:parser) { Jisota::ParamParser.new(params, args) }
6
+ let(:params) { [] }
7
+ let(:args) { [] }
8
+
9
+ def should_raise(error)
10
+ expect { subject }.to raise_exception(error)
11
+ end
12
+
13
+ context "no params" do
14
+ context "no args" do
15
+ it { should eq Hash.new }
16
+ end
17
+
18
+ context "implicit arg" do
19
+ let(:args) { [42] }
20
+ it { should_raise(Jisota::ParameterError) }
21
+ end
22
+
23
+ context "hash arg" do
24
+ let(:args) { [ { foo: 42 } ] }
25
+ it { should_raise(Jisota::ParameterError) }
26
+ end
27
+ end
28
+
29
+ context "param with no options" do
30
+ let(:params) { [Jisota::Param.new(:foo)] }
31
+
32
+ context "no args" do
33
+ it { should eq({foo: nil}) }
34
+ end
35
+
36
+ context "implicit arg" do
37
+ let(:args) { [42] }
38
+ it { should eq({foo: 42}) }
39
+ end
40
+
41
+ context "repeated implicit arg" do
42
+ let(:args) { [42, { foo: 42 }] }
43
+ it { should_raise(Jisota::ParameterError) }
44
+ end
45
+
46
+ context "hash arg" do
47
+ let(:args) { [ { foo: 42 } ] }
48
+ it { should eq({foo: 42}) }
49
+ end
50
+ end
51
+
52
+ context "param with required: true" do
53
+ let(:params) { [Jisota::Param.new(:foo, required: true)] }
54
+
55
+ context "no args" do
56
+ it { should_raise(Jisota::ParameterError) }
57
+ end
58
+
59
+ context "implicit arg" do
60
+ let(:args) { [42] }
61
+ it { should eq({foo: 42}) }
62
+ end
63
+
64
+ context "hash arg" do
65
+ let(:args) { [ { foo: 42 } ] }
66
+ it { should eq({foo: 42}) }
67
+ end
68
+ end
69
+
70
+ context "param with default" do
71
+ let(:params) { [Jisota::Param.new(:foo, default: 48)] }
72
+
73
+ context "no args" do
74
+ it { should eq({foo: 48}) }
75
+ end
76
+
77
+ context "implicit arg" do
78
+ let(:args) { [42] }
79
+ it { should eq({foo: 42}) }
80
+ end
81
+
82
+ context "hash arg" do
83
+ let(:args) { [ { foo: 42 } ] }
84
+ it { should eq({foo: 42}) }
85
+ end
86
+ end
87
+
88
+ context "param with splat: true" do
89
+ let(:params) { [Jisota::Param.new(:foo, splat: true)] }
90
+
91
+ context "no args" do
92
+ it { should eq({foo: []}) }
93
+ end
94
+
95
+ context "implicit arg" do
96
+ let(:args) { [42] }
97
+ it { should eq({foo: [42]}) }
98
+ end
99
+
100
+ context "hash arg" do
101
+ let(:args) { [ { foo: 42 } ] }
102
+ it { should_raise(Jisota::ParameterError) }
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module Jisota
4
+ describe Provisioner do
5
+ describe "#run" do
6
+
7
+ let(:ssh_engine) do
8
+ instance_double(SSHEngine).tap do |ssh|
9
+ allow(ssh).to receive(:start).with({user: "john", host: "123.456.789.0"}).and_yield(ssh_session)
10
+ end
11
+ end
12
+ let(:ssh_session) { instance_double(SSHSession, command: 0) }
13
+
14
+ it "executes a script" do
15
+ config = Configuration.new do
16
+ role :app do
17
+ cmd "touch foo"
18
+ end
19
+ server "123.456.789.0", user: "john", roles: :app
20
+ end
21
+ config.ssh_engine = ssh_engine
22
+
23
+ provisioner = Provisioner.new
24
+ provisioner.run(config, NilOutput.new)
25
+
26
+ expect(ssh_session).to have_received(:command).with("touch foo", anything)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -20,9 +20,7 @@ module Jisota
20
20
 
21
21
  describe "DSL" do
22
22
  it "initializes with DSL" do
23
- role = Role.new(:app) do
24
- cmd "touch foo"
25
- end
23
+ role = Role.new(:app) { cmd "touch foo" }
26
24
  expect(role.name).to eq(:app)
27
25
  expect(role.script_block).to be_a(ScriptBlock)
28
26
  end
@@ -23,13 +23,15 @@ module Jisota
23
23
  expect(script.scripts[0]).to be_a(CommandScript)
24
24
  expect(script.scripts[0].command).to eq("foo")
25
25
  expect(script.scripts[1]).to be_a(FileScript)
26
- expect(script.scripts[1].file).to eq(UploadFile.new("x", "y"))
26
+ expect(script.scripts[1].from).to eq("x")
27
+ expect(script.scripts[1].to).to eq("y")
27
28
  end
28
29
 
29
30
  it "parses args" do
30
31
  script_block = ScriptBlock.new { cmd "touch #{foo}" }
31
- args = { foo: "bar" }
32
- script = script_block.evaluate(args)
32
+ params = { foo: "bar" }
33
+ context = ScriptContext.new(params: params)
34
+ script = script_block.evaluate(context)
33
35
 
34
36
  expect(script.scripts.first.command).to eq("touch bar")
35
37
  end
@@ -38,8 +40,9 @@ module Jisota
38
40
  script_block = ScriptBlock.new { touch "file" }
39
41
  packages = Collection.new
40
42
  packages << Package.new(:touch)
43
+ context = ScriptContext.new(packages: packages)
41
44
 
42
- script = script_block.evaluate({}, packages)
45
+ script = script_block.evaluate(context)
43
46
  script = script.scripts.first
44
47
 
45
48
  expect(script).to be_a(PackageScript)
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module Jisota
4
+ describe SSHEngine do
5
+ describe "#start" do
6
+ let(:engine) do
7
+ class_double(Net::SSH).tap do |engine|
8
+ allow(engine).to receive(:start).and_yield(nil)
9
+ end
10
+ end
11
+ let(:wrapper) { SSHEngine.new(engine: engine) }
12
+
13
+ it "starts the engine" do
14
+ wrapper.start(user: "john", host: "foo") { |ssh_session| }
15
+
16
+ expect(engine).to have_received(:start).with("foo", "john", {})
17
+ end
18
+
19
+ it "passes extra options to engine" do
20
+ wrapper.start(user: "john", host: "foo", foo: "bar", bar: "baz") { |ssh_session| }
21
+
22
+ expect(engine).to have_received(:start).with("foo", "john", { foo: "bar", bar: "baz" })
23
+ end
24
+ end
25
+ end
26
+ end