vito 0.0.2 → 0.0.4

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rvmrc +1 -0
  4. data/README.md +33 -7
  5. data/Rakefile +35 -0
  6. data/Vagrantfile +1 -1
  7. data/bin/vito +7 -2
  8. data/docs/manual.md +79 -0
  9. data/lib/samples/vito_for_rails.rb +14 -0
  10. data/lib/vito.rb +2 -2
  11. data/lib/vito/connection.rb +20 -27
  12. data/lib/vito/dsl/installation.rb +15 -0
  13. data/lib/vito/dsl/server.rb +17 -0
  14. data/lib/vito/dsl_file.rb +24 -0
  15. data/lib/vito/log.rb +7 -1
  16. data/lib/vito/operating_system.rb +1 -11
  17. data/lib/vito/operating_systems/ubuntu_10.rb +31 -0
  18. data/lib/vito/output.rb +21 -0
  19. data/lib/vito/recipe.rb +6 -3
  20. data/lib/vito/recipes/postgres.rb +104 -0
  21. data/lib/vito/recipes/rbenv.rb +10 -5
  22. data/lib/vito/shell_initializer.rb +7 -12
  23. data/lib/vito/version.rb +1 -1
  24. data/spec/acceptance/recipes/git_acceptance_spec.rb +20 -0
  25. data/spec/acceptance/recipes/postgres_acceptance_spec.rb +20 -0
  26. data/spec/acceptance/recipes/rbenv_acceptance_spec.rb +22 -0
  27. data/spec/acceptance/recipes/ruby_acceptance_spec.rb +24 -0
  28. data/spec/spec_helper.rb +10 -0
  29. data/spec/support/vagrant.rb +34 -0
  30. data/spec/vito/connection_spec.rb +7 -4
  31. data/spec/vito/dsl/installation_spec.rb +17 -0
  32. data/spec/vito/dsl/server_spec.rb +0 -0
  33. data/spec/vito/dsl_file_spec.rb +37 -0
  34. data/spec/vito/log_spec.rb +10 -1
  35. data/spec/vito/operating_system_spec.rb +16 -0
  36. data/spec/vito/operating_systems/ubuntu_10_spec.rb +29 -0
  37. data/spec/vito/output_spec.rb +27 -5
  38. data/spec/vito/recipe_spec.rb +78 -0
  39. data/spec/vito/recipes/git_spec.rb +1 -1
  40. data/spec/vito/recipes/ruby_spec.rb +7 -35
  41. data/spec/vito/shell_initializer_spec.rb +10 -51
  42. data/vito.rb +3 -2
  43. metadata +33 -15
  44. data/lib/vito/installation.rb +0 -13
  45. data/lib/vito/logger.rb +0 -15
  46. data/lib/vito/recipes_configuration.rb +0 -11
  47. data/lib/vito/server.rb +0 -15
  48. data/lib/vito/ssh.rb +0 -62
  49. data/spec/contracts/vito/installation_contract.rb +0 -8
  50. data/spec/vito/installation_spec.rb +0 -25
  51. data/spec/vito/recipes_configuration_spec.rb +0 -7
  52. data/spec/vito/recipes_spec.rb +0 -9
@@ -0,0 +1,21 @@
1
+ module Vito
2
+ class ConnectionOutput
3
+ def initialize(stdin, stdout, stderr, thread)
4
+ @stdout = stdout
5
+ @stderr = stderr
6
+ @thread = thread.value
7
+ end
8
+
9
+ def success?
10
+ @thread.exitstatus == 0
11
+ end
12
+
13
+ def result
14
+ if success?
15
+ @result ||= @stdout.read
16
+ else
17
+ @result ||= @stderr.read
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/vito/recipe.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  module Vito
2
+
3
+ # This is a parent class for recipes and shouldn't be used directly.
2
4
  class Recipe
3
5
  def initialize(options, connection)
4
6
  @options = options
@@ -10,7 +12,7 @@ module Vito
10
12
  end
11
13
 
12
14
  def depends_on_recipe(recipe, options = {})
13
- Installation.new(recipe, options, @connection).install
15
+ Dsl::Installation.new(recipe, options, @connection).install
14
16
  end
15
17
 
16
18
  def run_command(command)
@@ -28,10 +30,11 @@ module Vito
28
30
  Vito::Utils::ProgramVersion.new(version_command, @connection)
29
31
  end
30
32
 
31
- private
33
+ def os
34
+ @os ||= Vito::OperatingSystem.new(@connection).os
35
+ end
32
36
 
33
37
  def install_os_dependencies
34
- os = Vito::OperatingSystem.new(@connection)
35
38
  os.update_packages
36
39
  os.install_dependencies(os_dependencies) if self.respond_to?(:os_dependencies)
37
40
  end
@@ -0,0 +1,104 @@
1
+ module Vito
2
+ module Recipes
3
+ class Postgres < Vito::Recipe
4
+ def run
5
+ if installed?
6
+ Vito::Log.write "Postgres already installed."
7
+ else
8
+ Vito::Log.write "Installing Postgres"
9
+ install_os_dependencies
10
+ install
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def postgres_installed?
17
+ @memo ||= query("psql --version").success?
18
+ end
19
+
20
+ def user_exists?
21
+ query("sudo su - postgres -c \"psql -tAc \\\\\"SELECT 1 FROM pg_roles WHERE rolname='#{username}'\\\\\" | grep -q 1 || echo 'hey'\"").result == ""
22
+ end
23
+
24
+ def utf_template?
25
+ query("sudo su - postgres -c \"psql -d template1 -c \\\\\"SHOW SERVER_ENCODING;\\\\\" | grep -q UTF || echo 'hey'\"").result == ""
26
+ end
27
+
28
+ def installed?
29
+ # Only verifies Postgres configuration if it's installed
30
+ if postgres_installed?
31
+ Vito::Log.write "User doesn't exist. I will create one." unless user_exists?
32
+ Vito::Log.write "template1 database's encoding should be UTF-8. I'll adjust this." unless utf_template?
33
+ end
34
+
35
+ postgres_installed? &&
36
+ user_exists? &&
37
+ utf_template?
38
+ end
39
+
40
+ def username
41
+ "vitouser"
42
+ end
43
+
44
+ def password
45
+ "123456"
46
+ end
47
+
48
+ def install
49
+ string = []
50
+ run_command "sudo apt-get install -y postgresql-9.1 libpq-dev"
51
+
52
+ # Create user only if it doesn't exist yet
53
+ unless user_exists?
54
+ string << "sudo su - postgres -c \"createuser -d -r -s #{username}\""
55
+ end
56
+
57
+ run_command(string.join(" && ")) unless string.empty?
58
+ convert_template1_to_utf8 unless utf_template?
59
+ string = []
60
+
61
+ if os.is?(:ubuntu, "10")
62
+ string << "sudo /etc/init.d/postgresql restart"
63
+ else
64
+ string << "sudo service postgresql restart"
65
+ end
66
+ run_command "sudo su - postgres -c \"psql -d template1 -c \\\\\"alter user #{username} with password '#{password}'\\\\\";\""
67
+
68
+ run_command(string.join(" && "))
69
+ end
70
+
71
+ def install_os_dependencies
72
+ return if postgres_installed?
73
+ Vito::Log.write "Installing some OS dependencies first"
74
+ if os.is?(:ubuntu, "10")
75
+ run_command("sudo apt-get remove -y postgresql")
76
+ run_command("sudo apt-get autoremove -y")
77
+ run_command("sudo apt-get install -y python-software-properties")
78
+ run_command("sudo add-apt-repository ppa:pitti/postgresql && sudo apt-get update")
79
+ end
80
+
81
+ super
82
+ end
83
+
84
+ def os_dependencies
85
+ %w(libpq-dev postgresql-contrib)
86
+ end
87
+
88
+ def convert_template1_to_utf8
89
+ # In some cases, the OS locale won't be compatible with UTF-8. When
90
+ # creating a database, Rails will try to use Postgres' template1 with
91
+ # UTF-8.
92
+ #
93
+ # Here, we delete template1, then login in template0 to recreate
94
+ # template1 with UTF-8 encoding.
95
+ run_command "sudo su - postgres -c \"psql -d template1 -c \\\\\"UPDATE pg_database SET datallowconn = TRUE where datname = 'template0';\\\\\"\""
96
+ run_command "sudo su - postgres -c \"psql -d template0 -c \\\\\"UPDATE pg_database SET datistemplate = FALSE where datname = 'template1'; \\\\\"\""
97
+ run_command "sudo su - postgres -c \"psql -d template0 -c \\\\\"drop database template1; \\\\\"\""
98
+ run_command "sudo su - postgres -c \"psql -d template0 -c \\\\\"create database template1 with template = template0 encoding = 'UNICODE' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'C'; \\\\\"\""
99
+ run_command "sudo su - postgres -c \"psql -d template0 -c \\\\\" UPDATE pg_database SET datistemplate = TRUE where datname = 'template1'; \\\\\"\""
100
+ run_command "sudo su - postgres -c \"psql -d template1 -c \\\\\" UPDATE pg_database SET datallowconn = FALSE where datname = 'template0'; \\\\\"\""
101
+ end
102
+ end
103
+ end
104
+ end
@@ -22,18 +22,23 @@ module Vito
22
22
  end
23
23
 
24
24
  def install_rbenv
25
- puts "Installing rbenv..."
25
+ puts "Installing Rbenv..."
26
26
  string = []
27
- string << "git clone git://github.com/sstephenson/rbenv.git ~/.rbenv"
28
- string << "echo 'export PATH=\"\\$HOME/.rbenv/bin:\\$PATH\"' >> ~/.profile"
29
- string << "echo 'eval \"$(rbenv init -)\"' >> ~/.profile"
30
- string << "exec \\$SHELL -l"
27
+ # TODO verify if this folder already exists
28
+ run_command "git clone git://github.com/sstephenson/rbenv.git ~/.rbenv"
29
+
30
+ # TODO verify if .bashrc already have these lines
31
+ string = []
32
+ string << "echo 'eval \"$(rbenv init -)\"' | cat - ~/.bashrc > vitotemp && mv vitotemp ~/.bashrc"
33
+ string << "echo 'export PATH=\"\\$HOME/.rbenv/bin:\\$PATH\"' | cat - ~/.bashrc > vitotemp && mv vitotemp ~/.bashrc"
34
+
31
35
  run_command string.join(" && ")
32
36
  end
33
37
 
34
38
  def install_ruby_build
35
39
  puts "Installing ruby-build embedded into rbenv..."
36
40
  string = []
41
+ # TODO verify if this dir already exists
37
42
  string << "git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build"
38
43
  run_command string.join(" && ")
39
44
  end
@@ -2,25 +2,20 @@ require "vito/recipes/ruby"
2
2
 
3
3
  module Vito
4
4
  class ShellInitializer
5
- attr_reader :ssh
6
-
7
- def initialize(args)
8
- @installation_specs = File.open("vito.rb").read
5
+ def initialize(argv)
6
+ @argv = argv
9
7
  end
10
8
 
11
9
  def run
12
- run_vito_file
13
- end
14
-
15
- # called by the vito.rb file
16
- def server(*args, &block)
17
- Vito::Server.new.instance_eval &block
10
+ Vito::DslFile.new(argv).run(vito_file)
18
11
  end
19
12
 
20
13
  private
21
14
 
22
- def run_vito_file
23
- instance_eval @installation_specs
15
+ attr_reader :argv
16
+
17
+ def vito_file
18
+ File.open("vito.rb").read
24
19
  end
25
20
  end
26
21
  end
data/lib/vito/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vito
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "Git recipe" do
4
+ before do
5
+ setup_vagrant
6
+ end
7
+
8
+ it "installs Git" do
9
+ assert_installation("git --version").should be_false
10
+
11
+ Vito::DslFile.new.run do
12
+ server do
13
+ connection :ssh, command: 'ssh -i ~/.vagrant.d/insecure_private_key vagrant@localhost -p2222', silent: true
14
+ install :git
15
+ end
16
+ end
17
+
18
+ assert_installation("git --version").should be_true
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "Postgres recipe" do
4
+ before do
5
+ setup_vagrant
6
+ end
7
+
8
+ it "installs Postgres" do
9
+ assert_installation("psql --version").should be_false
10
+
11
+ Vito::DslFile.new.run do
12
+ server do
13
+ connection :ssh, command: 'ssh -i ~/.vagrant.d/insecure_private_key vagrant@localhost -p2222', silent: true
14
+ install :postgres
15
+ end
16
+ end
17
+
18
+ assert_installation("psql --version").should be_true
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe "Rbenv recipe" do
4
+ before do
5
+ setup_vagrant
6
+ end
7
+
8
+ it "installs Git and then Rbenv" do
9
+ assert_installation("git --version").should be_false
10
+ assert_installation("rbenv --version").should be_false
11
+
12
+ Vito::DslFile.new.run do
13
+ server do
14
+ connection :ssh, command: 'ssh -i ~/.vagrant.d/insecure_private_key vagrant@localhost -p2222', silent: true
15
+ install :rbenv
16
+ end
17
+ end
18
+
19
+ assert_installation("git --version").should be_true
20
+ assert_installation("rbenv --version").should be_true
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require "spec_helper"
2
+
3
+ describe "Ruby recipe" do
4
+ before do
5
+ setup_vagrant
6
+ end
7
+
8
+ it "installs Git, Rbenv and then Ruby" do
9
+ assert_installation("git --version").should be_false
10
+ assert_installation("rbenv --version").should be_false
11
+ assert_installation("ruby -v").should be_false
12
+
13
+ Vito::DslFile.new.run do
14
+ server do
15
+ connection :ssh, command: 'ssh -i ~/.vagrant.d/insecure_private_key vagrant@localhost -p2222', silent: true
16
+ install :ruby, version: "1.9.3-p125"
17
+ end
18
+ end
19
+
20
+ assert_installation("git --version").should be_true
21
+ assert_installation("rbenv --version").should be_true
22
+ assert_installation("ruby -v").should be_true
23
+ end
24
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,12 @@
1
+ ENV["env"] ||= "test"
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
1
3
  require "rubygems"
2
4
  require "bundler/setup"
5
+ require "open3"
6
+ require "vito"
7
+
8
+ Dir["./spec/support/*.rb"].each { |f| require f }
9
+
10
+ RSpec.configure do |config|
11
+ config.include RSpecSupport::Vagrant
12
+ end
@@ -0,0 +1,34 @@
1
+ module RSpecSupport
2
+ module Vagrant
3
+ def connection
4
+ 'ssh -i ~/.vagrant.d/insecure_private_key vagrant@localhost -p2222'
5
+ end
6
+
7
+ def setup_vagrant
8
+ system_command("vagrant up")
9
+ raise "Box not working" unless vagrant_command("ls")
10
+ reboot_vagrant_box
11
+ end
12
+
13
+ def assert_installation(command)
14
+ vagrant_command(command)
15
+ end
16
+
17
+ def reboot_vagrant_box
18
+ system_command("vagrant snapshot go initial_box")
19
+ end
20
+
21
+ private
22
+
23
+ def system_command(command)
24
+ stdin, stdout, stderr, thread = Open3.popen3(command)
25
+ thread.value.exitstatus == 0
26
+ end
27
+
28
+ def vagrant_command(command)
29
+ command = "#{connection} #{command}"
30
+ stdin, stdout, stderr, thread = Open3.popen3(command)
31
+ thread.value.exitstatus == 0
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,4 @@
1
1
  require "spec_helper"
2
- require "vito/connection"
3
- require "vito/log"
4
2
 
5
3
  describe Vito::Connection do
6
4
  before do
@@ -20,8 +18,13 @@ describe Vito::Connection do
20
18
  context "invalid command" do
21
19
  let(:command) { "harrr" }
22
20
 
23
- its(:success?) { should be_false }
24
- its(:result) { should == "sh: harrr: command not found\n" }
21
+ it "raises error and logs its messages" do
22
+ Vito::Log.should_receive(:raise).with("An error occurred. Here's the stacktrace:")
23
+ Vito::Log.should_receive(:raise).with("sh: harrr: command not found\n")
24
+ Vito::Log.stub(:raise)
25
+
26
+ expect{ subject }.to raise_error "Error."
27
+ end
25
28
  end
26
29
  end
27
30
  end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe Vito::Dsl::Installation do
4
+ let(:connection) { double }
5
+ let(:ruby) { double }
6
+ let(:options) { {version: "2.0.0"} }
7
+
8
+ subject { described_class.new(:ruby, options, connection) }
9
+
10
+ describe "#install" do
11
+ it "installs each recipes" do
12
+ ruby.should_receive(:run)
13
+ Vito::Recipes::Ruby.stub(:new).with(options, connection) { ruby }
14
+ subject.install
15
+ end
16
+ end
17
+ end
File without changes
@@ -0,0 +1,37 @@
1
+ require "vito/dsl_file"
2
+
3
+ describe Vito::DslFile do
4
+ let(:server) { double }
5
+
6
+ subject { described_class.new }
7
+
8
+ before do
9
+ stub_const("Vito::Dsl::Server", Class.new)
10
+ end
11
+
12
+ describe "#run" do
13
+ before do
14
+ Vito::Dsl::Server.stub(:new).with([:hey]) { server }
15
+ end
16
+
17
+ it "runs the server block evaluating it as string" do
18
+ server.should_receive(:instance_eval)
19
+
20
+ subject.run <<-str
21
+ server :hey do
22
+
23
+ end
24
+ str
25
+ end
26
+
27
+ it "runs the server as a Ruby block" do
28
+ server.should_receive(:instance_eval)
29
+
30
+ subject.run do
31
+ server :hey do
32
+
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end