vito 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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +0 -0
- data/LICENSE +0 -0
- data/README.md +32 -9
- data/Rakefile +11 -0
- data/Vagrantfile +99 -0
- data/bin/vito +7 -0
- data/lib/vito.rb +6 -2
- data/lib/vito/connection.rb +67 -0
- data/lib/vito/installation.rb +13 -0
- data/lib/vito/log.rb +11 -0
- data/lib/vito/logger.rb +15 -0
- data/lib/vito/operating_system.rb +21 -0
- data/lib/vito/recipe.rb +39 -0
- data/lib/vito/recipes/git.rb +37 -0
- data/lib/vito/recipes/rbenv.rb +42 -0
- data/lib/vito/recipes/ruby.rb +43 -0
- data/lib/vito/recipes_configuration.rb +11 -0
- data/lib/vito/server.rb +15 -0
- data/lib/vito/shell_initializer.rb +26 -0
- data/lib/vito/ssh.rb +62 -0
- data/lib/vito/utils/program_version.rb +24 -0
- data/lib/vito/version.rb +1 -1
- data/spec/contracts/vito/installation_contract.rb +8 -0
- data/spec/fixtures/vito.rb +27 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/vito/connection_spec.rb +27 -0
- data/spec/vito/installation_spec.rb +25 -0
- data/spec/vito/log_spec.rb +10 -0
- data/spec/vito/output_spec.rb +10 -0
- data/spec/vito/recipes/git_spec.rb +8 -0
- data/spec/vito/recipes/ruby_spec.rb +52 -0
- data/spec/vito/recipes_configuration_spec.rb +7 -0
- data/spec/vito/recipes_spec.rb +9 -0
- data/spec/vito/shell_initializer_spec.rb +63 -0
- data/spec/vito/utils/program_version_spec.rb +44 -0
- data/vito.gemspec +6 -3
- data/vito.rb +11 -0
- metadata +91 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 273dc6976a1c63197a0576ebe4ef79ec7270c0ed
|
4
|
+
data.tar.gz: 01c117e4e67876913b201ca883bdcef79eb536a4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c406ea381b7ae439ff5bac7670a67381e7f95382189a685882bef8c819e6f04291eb00bde33d17e37f439dc8f346ede010e1685496fabbe384057e2d2aacabcd
|
7
|
+
data.tar.gz: e722b05a007fd7d19f59fa45b528bace134d56d73bdca3a3ed447d99f830310ca5c8c9b19cd2b9e721ed53ff41dbd260cc9b9497b415632ef9b41363e7ebba12
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
CHANGED
File without changes
|
data/LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -1,24 +1,47 @@
|
|
1
1
|
# Vito
|
2
2
|
|
3
|
-
|
3
|
+
Vito installs webservers for you very easily. Its goal is to be opinionated,
|
4
|
+
with a shallow learning curve needed due to the use of a Gemfile-like specification
|
5
|
+
file.
|
4
6
|
|
5
|
-
|
7
|
+
```ruby
|
8
|
+
server :linode do
|
9
|
+
connection :ssh, :command => "vagrant ssh -c" }
|
6
10
|
|
7
|
-
|
11
|
+
install :rbenv
|
12
|
+
install :git
|
13
|
+
install :ruby, version: "2.0.0-p195"
|
14
|
+
install :tmux
|
15
|
+
install :apache do
|
16
|
+
vhosts_for :rails, port: 80
|
17
|
+
vhosts_for :rails, port: 443
|
18
|
+
end
|
19
|
+
install :passenger, with: :apache
|
20
|
+
end
|
8
21
|
|
9
|
-
|
22
|
+
server :ec2 do
|
23
|
+
install :postgres do
|
24
|
+
allow_connection from: :linode
|
25
|
+
end
|
10
26
|
|
11
|
-
|
27
|
+
# ...
|
28
|
+
end
|
29
|
+
```
|
12
30
|
|
13
|
-
|
31
|
+
Along with the installation process, it'll also be able to output status reports
|
32
|
+
about a particular server.
|
14
33
|
|
15
|
-
|
34
|
+
For now, it won't be hosted, just sending SSH messages instead.
|
16
35
|
|
17
|
-
|
36
|
+
## Working packages
|
37
|
+
|
38
|
+
These are the packages that are currently working:
|
39
|
+
|
40
|
+
rbenv, git, ruby
|
18
41
|
|
19
42
|
## Usage
|
20
43
|
|
21
|
-
|
44
|
+
Vito is not read for production yet.
|
22
45
|
|
23
46
|
## Contributing
|
24
47
|
|
data/Rakefile
CHANGED
@@ -1,2 +1,13 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
desc "Sets up a Vagrant box for running specs"
|
5
|
+
namespace :setup do
|
6
|
+
task :download_vagrant_box do
|
7
|
+
# list of boxes http://www.vagrantbox.es/
|
8
|
+
puts "Downloading Vagrant box called ubuntu_spec_box"
|
9
|
+
system "vagrant box add ubuntu_spec_box http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box"
|
10
|
+
puts "Initializing box with Vagrant"
|
11
|
+
system "vagrant init ubuntu_spec_box"
|
12
|
+
end
|
13
|
+
end
|
data/Vagrantfile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
Vagrant::Config.run do |config|
|
5
|
+
# All Vagrant configuration is done here. The most common configuration
|
6
|
+
# options are documented and commented below. For a complete reference,
|
7
|
+
# please see the online documentation at vagrantup.com.
|
8
|
+
|
9
|
+
# Every Vagrant virtual environment requires a box to build off of.
|
10
|
+
config.vm.box = "ubuntu_spec_box"
|
11
|
+
|
12
|
+
# The url from where the 'config.vm.box' box will be fetched if it
|
13
|
+
# doesn't already exist on the user's system.
|
14
|
+
# config.vm.box_url = "http://domain.com/path/to/above.box"
|
15
|
+
|
16
|
+
# Boot with a GUI so you can see the screen. (Default is headless)
|
17
|
+
# config.vm.boot_mode = :gui
|
18
|
+
|
19
|
+
# Assign this VM to a host-only network IP, allowing you to access it
|
20
|
+
# via the IP. Host-only networks can talk to the host machine as well as
|
21
|
+
# any other machines on the same network, but cannot be accessed (through this
|
22
|
+
# network interface) by any external networks.
|
23
|
+
# config.vm.network :hostonly, "192.168.33.10"
|
24
|
+
|
25
|
+
# Assign this VM to a bridged network, allowing you to connect directly to a
|
26
|
+
# network using the host's network device. This makes the VM appear as another
|
27
|
+
# physical device on your network.
|
28
|
+
# config.vm.network :bridged
|
29
|
+
|
30
|
+
# Forward a port from the guest to the host, which allows for outside
|
31
|
+
# computers to access the VM, whereas host only networking does not.
|
32
|
+
config.vm.forward_port 23, 22
|
33
|
+
|
34
|
+
# Share an additional folder to the guest VM. The first argument is
|
35
|
+
# an identifier, the second is the path on the guest to mount the
|
36
|
+
# folder, and the third is the path on the host to the actual folder.
|
37
|
+
# config.vm.share_folder "v-data", "/vagrant_data", "../data"
|
38
|
+
|
39
|
+
# Enable provisioning with Puppet stand alone. Puppet manifests
|
40
|
+
# are contained in a directory path relative to this Vagrantfile.
|
41
|
+
# You will need to create the manifests directory and a manifest in
|
42
|
+
# the file ubuntu_spec_box.pp in the manifests_path directory.
|
43
|
+
#
|
44
|
+
# An example Puppet manifest to provision the message of the day:
|
45
|
+
#
|
46
|
+
# # group { "puppet":
|
47
|
+
# # ensure => "present",
|
48
|
+
# # }
|
49
|
+
# #
|
50
|
+
# # File { owner => 0, group => 0, mode => 0644 }
|
51
|
+
# #
|
52
|
+
# # file { '/etc/motd':
|
53
|
+
# # content => "Welcome to your Vagrant-built virtual machine!
|
54
|
+
# # Managed by Puppet.\n"
|
55
|
+
# # }
|
56
|
+
#
|
57
|
+
# config.vm.provision :puppet do |puppet|
|
58
|
+
# puppet.manifests_path = "manifests"
|
59
|
+
# puppet.manifest_file = "ubuntu_spec_box.pp"
|
60
|
+
# end
|
61
|
+
|
62
|
+
# Enable provisioning with chef solo, specifying a cookbooks path, roles
|
63
|
+
# path, and data_bags path (all relative to this Vagrantfile), and adding
|
64
|
+
# some recipes and/or roles.
|
65
|
+
#
|
66
|
+
# config.vm.provision :chef_solo do |chef|
|
67
|
+
# chef.cookbooks_path = "../my-recipes/cookbooks"
|
68
|
+
# chef.roles_path = "../my-recipes/roles"
|
69
|
+
# chef.data_bags_path = "../my-recipes/data_bags"
|
70
|
+
# chef.add_recipe "mysql"
|
71
|
+
# chef.add_role "web"
|
72
|
+
#
|
73
|
+
# # You may also specify custom JSON attributes:
|
74
|
+
# chef.json = { :mysql_password => "foo" }
|
75
|
+
# end
|
76
|
+
|
77
|
+
# Enable provisioning with chef server, specifying the chef server URL,
|
78
|
+
# and the path to the validation key (relative to this Vagrantfile).
|
79
|
+
#
|
80
|
+
# The Opscode Platform uses HTTPS. Substitute your organization for
|
81
|
+
# ORGNAME in the URL and validation key.
|
82
|
+
#
|
83
|
+
# If you have your own Chef Server, use the appropriate URL, which may be
|
84
|
+
# HTTP instead of HTTPS depending on your configuration. Also change the
|
85
|
+
# validation key to validation.pem.
|
86
|
+
#
|
87
|
+
# config.vm.provision :chef_client do |chef|
|
88
|
+
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
|
89
|
+
# chef.validation_key_path = "ORGNAME-validator.pem"
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# If you're using the Opscode platform, your validator client is
|
93
|
+
# ORGNAME-validator, replacing ORGNAME with your organization name.
|
94
|
+
#
|
95
|
+
# IF you have your own Chef Server, the default validation client name is
|
96
|
+
# chef-validator, unless you changed the configuration.
|
97
|
+
#
|
98
|
+
# chef.validation_client_name = "ORGNAME-validator"
|
99
|
+
end
|
data/bin/vito
ADDED
data/lib/vito.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "open3"
|
2
|
+
|
3
|
+
module Vito
|
4
|
+
class Connection
|
5
|
+
def initialize(type, args = {})
|
6
|
+
@options = {}
|
7
|
+
@options[:command] = args[:command]
|
8
|
+
end
|
9
|
+
|
10
|
+
def query(command)
|
11
|
+
command = final_command(command)
|
12
|
+
execute_command(command)
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(command)
|
16
|
+
command = final_command(command)
|
17
|
+
Log.write "* Executing: #{command}"
|
18
|
+
output = execute_command(command)
|
19
|
+
|
20
|
+
unless output.success?
|
21
|
+
Log.write "An error occurred. Here's the stacktrace:"
|
22
|
+
Log.write output.result
|
23
|
+
Log.write ""
|
24
|
+
end
|
25
|
+
|
26
|
+
output
|
27
|
+
end
|
28
|
+
|
29
|
+
class Output
|
30
|
+
def initialize(stdin, stdout, stderr, thread)
|
31
|
+
@stdout = stdout
|
32
|
+
@stderr = stderr
|
33
|
+
@thread = thread.value
|
34
|
+
end
|
35
|
+
|
36
|
+
def success?
|
37
|
+
@thread.exitstatus == 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def result
|
41
|
+
if success?
|
42
|
+
@stdout.read
|
43
|
+
else
|
44
|
+
@stderr.read
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_reader :options
|
52
|
+
|
53
|
+
def execute_command(command)
|
54
|
+
stdin, stdout, stderr, thread = []
|
55
|
+
Bundler.with_clean_env do
|
56
|
+
stdin, stdout, stderr, thread = Open3.popen3(command)
|
57
|
+
end
|
58
|
+
Output.new(stdin, stdout, stderr, thread)
|
59
|
+
end
|
60
|
+
|
61
|
+
def final_command(command)
|
62
|
+
command = command.gsub(/"/, '\"')
|
63
|
+
command = command.gsub(/\$\(/, '\$(')
|
64
|
+
command = "#{@options[:command]} \"#{command}\""
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Vito
|
2
|
+
class Installation
|
3
|
+
def initialize(name, options, connection)
|
4
|
+
@name = name.to_s
|
5
|
+
@options = options
|
6
|
+
@connection = connection
|
7
|
+
end
|
8
|
+
|
9
|
+
def install
|
10
|
+
"Vito::Recipes::#{@name.camelize}".constantize.new(@options, @connection).run
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/vito/log.rb
ADDED
data/lib/vito/logger.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Vito
|
2
|
+
class OperatingSystem
|
3
|
+
def initialize(connection)
|
4
|
+
@connection = connection
|
5
|
+
end
|
6
|
+
|
7
|
+
def update_packages
|
8
|
+
os.update_packages
|
9
|
+
end
|
10
|
+
|
11
|
+
def install_dependencies(dependencies)
|
12
|
+
os.install_dependencies(dependencies)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def os
|
18
|
+
@os ||= Vito::OperatingSystem::Ubuntu10.new(@connection)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/vito/recipe.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Vito
|
2
|
+
class Recipe
|
3
|
+
def initialize(options, connection)
|
4
|
+
@options = options
|
5
|
+
@connection = connection
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
raise "#{self.class.name} recipe needs to define a #run method"
|
10
|
+
end
|
11
|
+
|
12
|
+
def depends_on_recipe(recipe, options = {})
|
13
|
+
Installation.new(recipe, options, @connection).install
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_command(command)
|
17
|
+
@connection.run(command)
|
18
|
+
end
|
19
|
+
|
20
|
+
def query(command)
|
21
|
+
@connection.query(command)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Helper methods
|
25
|
+
#
|
26
|
+
# should be extracted later
|
27
|
+
def program_version(version_command)
|
28
|
+
Vito::Utils::ProgramVersion.new(version_command, @connection)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def install_os_dependencies
|
34
|
+
os = Vito::OperatingSystem.new(@connection)
|
35
|
+
os.update_packages
|
36
|
+
os.install_dependencies(os_dependencies) if self.respond_to?(:os_dependencies)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Vito
|
2
|
+
module Recipes
|
3
|
+
class Git < Vito::Recipe
|
4
|
+
def run
|
5
|
+
if git_installed?
|
6
|
+
Vito::Log.write "Git is already installed."
|
7
|
+
else
|
8
|
+
Vito::Log.write "Installing Git's OS dependencies"
|
9
|
+
install_os_dependencies
|
10
|
+
Vito::Log.write "Installing Git itself"
|
11
|
+
install_git
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def git_installed?
|
18
|
+
query("git --version").success?
|
19
|
+
end
|
20
|
+
|
21
|
+
def install_git
|
22
|
+
string = []
|
23
|
+
string << "sudo apt-get install -y git-core"
|
24
|
+
string << "git --version"
|
25
|
+
run_command(string.join(" && "))
|
26
|
+
end
|
27
|
+
|
28
|
+
def os_dependencies
|
29
|
+
%w(build-essential openssl libreadline6
|
30
|
+
libreadline6-dev zlib1g zlib1g-dev libssl-dev
|
31
|
+
libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3
|
32
|
+
libxml2-dev libxslt1-dev autoconf libc6-dev
|
33
|
+
libncurses5-dev)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Vito
|
2
|
+
module Recipes
|
3
|
+
class Rbenv < Vito::Recipe
|
4
|
+
def run
|
5
|
+
if rbenv_installed?
|
6
|
+
Vito::Log.write "Rbenv already installed."
|
7
|
+
else
|
8
|
+
Vito::Log.write "Installing Rbenv"
|
9
|
+
depends_on_recipe(:git)
|
10
|
+
install_rbenv
|
11
|
+
install_ruby_build
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def rbenv_installed?
|
18
|
+
string = []
|
19
|
+
string << "cd ~/"
|
20
|
+
string << "rbenv commands"
|
21
|
+
query(string.join(" && ")).success?
|
22
|
+
end
|
23
|
+
|
24
|
+
def install_rbenv
|
25
|
+
puts "Installing rbenv..."
|
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"
|
31
|
+
run_command string.join(" && ")
|
32
|
+
end
|
33
|
+
|
34
|
+
def install_ruby_build
|
35
|
+
puts "Installing ruby-build embedded into rbenv..."
|
36
|
+
string = []
|
37
|
+
string << "git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build"
|
38
|
+
run_command string.join(" && ")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Vito
|
2
|
+
module Recipes
|
3
|
+
class Ruby < Vito::Recipe
|
4
|
+
def run
|
5
|
+
if ruby_exists?
|
6
|
+
Vito::Log.write "Ruby version #{version} is already installed."
|
7
|
+
else
|
8
|
+
Vito::Log.write "Installing Ruby"
|
9
|
+
install_os_dependencies
|
10
|
+
depends_on_recipe(:rbenv)
|
11
|
+
install_ruby
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def install_ruby
|
16
|
+
string = []
|
17
|
+
string << "rbenv install #{version}"
|
18
|
+
string << "rbenv global #{version}"
|
19
|
+
string << "rbenv rehash"
|
20
|
+
string << "gem install bundler"
|
21
|
+
run_command string.join(" && ")
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def ruby_exists?
|
27
|
+
program_version("ruby -v").matches?(version)
|
28
|
+
end
|
29
|
+
|
30
|
+
def os_dependencies
|
31
|
+
%w(build-essential openssl libreadline6
|
32
|
+
libreadline6-dev zlib1g zlib1g-dev libssl-dev
|
33
|
+
libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3
|
34
|
+
libxml2-dev libxslt1-dev autoconf libc6-dev
|
35
|
+
libncurses5-dev)
|
36
|
+
end
|
37
|
+
|
38
|
+
def version
|
39
|
+
@options[:version]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/vito/server.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Vito
|
2
|
+
class Server
|
3
|
+
def new
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
def connection(type, options = {})
|
8
|
+
@connection ||= Vito::Connection.new(type, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def install(name, options = {})
|
12
|
+
Vito::Installation.new(name, options, @connection).install
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "vito/recipes/ruby"
|
2
|
+
|
3
|
+
module Vito
|
4
|
+
class ShellInitializer
|
5
|
+
attr_reader :ssh
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
@installation_specs = File.open("vito.rb").read
|
9
|
+
end
|
10
|
+
|
11
|
+
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
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def run_vito_file
|
23
|
+
instance_eval @installation_specs
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/vito/ssh.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
#require 'net/ssh'
|
3
|
+
|
4
|
+
module Vito
|
5
|
+
class Ssh
|
6
|
+
def initialize(host, username)
|
7
|
+
@host = host
|
8
|
+
@username = username
|
9
|
+
@connection = Net::SSH.start(@host, @username)
|
10
|
+
puts "Opened SSH connection."
|
11
|
+
end
|
12
|
+
|
13
|
+
def close
|
14
|
+
@connection.close
|
15
|
+
puts "Closed SSH connection."
|
16
|
+
end
|
17
|
+
|
18
|
+
def run(command)
|
19
|
+
puts "\t['#{command}']"
|
20
|
+
stdout_data = ""
|
21
|
+
stderr_data = ""
|
22
|
+
exit_code = nil
|
23
|
+
exit_signal = nil
|
24
|
+
ssh = @connection
|
25
|
+
ssh.open_channel do |channel|
|
26
|
+
channel.exec(command) do |ch, success|
|
27
|
+
unless success
|
28
|
+
abort "FAILED: couldn't execute command (ssh.channel.exec)"
|
29
|
+
end
|
30
|
+
|
31
|
+
channel.on_data do |ch,data|
|
32
|
+
stdout_data+=data
|
33
|
+
end
|
34
|
+
|
35
|
+
channel.on_extended_data do |ch,type,data|
|
36
|
+
stderr_data+=data
|
37
|
+
end
|
38
|
+
|
39
|
+
channel.on_request("exit-status") do |ch,data|
|
40
|
+
exit_code = data.read_long
|
41
|
+
end
|
42
|
+
|
43
|
+
channel.on_request("exit-signal") do |ch, data|
|
44
|
+
exit_signal = data.read_long
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
ssh.loop
|
49
|
+
|
50
|
+
result = [stdout_data, stderr_data, exit_code, exit_signal]
|
51
|
+
if exit_code === 0
|
52
|
+
puts "\t[success]"
|
53
|
+
else
|
54
|
+
puts "\t[failure]"
|
55
|
+
puts "RESULT"
|
56
|
+
puts result.inspect
|
57
|
+
end
|
58
|
+
|
59
|
+
result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Vito
|
2
|
+
module Utils
|
3
|
+
class ProgramVersion
|
4
|
+
def initialize(version_command, connection)
|
5
|
+
@version_command = version_command
|
6
|
+
@connection = connection
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(version)
|
10
|
+
version = version.gsub(/-/, "(.*){,1}")
|
11
|
+
if output.success?
|
12
|
+
return output.result =~ /#{version}/
|
13
|
+
end
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def output
|
20
|
+
@output ||= @connection.query(@version_command)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/vito/version.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
class VitoConfig
|
2
|
+
def self.config
|
3
|
+
config = self.new
|
4
|
+
config.connection.merge use: config.config
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :config
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@config = {}
|
11
|
+
install
|
12
|
+
end
|
13
|
+
|
14
|
+
def connection
|
15
|
+
{ user: "root",
|
16
|
+
host: "50.116.3.20"
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def install
|
21
|
+
use :ruby, "1.9.3-p125"
|
22
|
+
end
|
23
|
+
|
24
|
+
def use(program, *details)
|
25
|
+
@config[program.to_sym] = details
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "vito/connection"
|
3
|
+
require "vito/log"
|
4
|
+
|
5
|
+
describe Vito::Connection do
|
6
|
+
before do
|
7
|
+
STDOUT.stub(:puts)
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { described_class.new(:ssh, {command: command}).run("Alex") }
|
11
|
+
|
12
|
+
describe "#run" do
|
13
|
+
context "valid command" do
|
14
|
+
let(:command) { "echo" }
|
15
|
+
|
16
|
+
its(:success?) { should == true }
|
17
|
+
its(:result) { should == "Alex\n" }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "invalid command" do
|
21
|
+
let(:command) { "harrr" }
|
22
|
+
|
23
|
+
its(:success?) { should be_false }
|
24
|
+
its(:result) { should == "sh: harrr: command not found\n" }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "vito/installation"
|
2
|
+
require "contracts/vito/installation_contract"
|
3
|
+
|
4
|
+
describe Vito::Installation do
|
5
|
+
it_behaves_like "installation contract"
|
6
|
+
|
7
|
+
let(:config) { {use: {ruby: "1.9.3"}} }
|
8
|
+
let(:requestor) { double(config: config) }
|
9
|
+
subject { Vito::Installation.new(requestor) }
|
10
|
+
|
11
|
+
describe "#install" do
|
12
|
+
before do
|
13
|
+
stub_const("Vito::Ssh", Object.new)
|
14
|
+
stub_const("Vito::Recipes::Ruby", Object.new)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "installs each recipes" do
|
18
|
+
ruby = double
|
19
|
+
ruby.should_receive(:run)
|
20
|
+
Vito::Recipes::Ruby.stub(:new).with(subject) { ruby }
|
21
|
+
|
22
|
+
subject.install
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "vito/recipes/ruby"
|
2
|
+
|
3
|
+
describe Vito::Recipes::Ruby do
|
4
|
+
let(:vito) { double }
|
5
|
+
|
6
|
+
subject { Vito::Recipes::Ruby.new(vito) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_const("Vito::Recipes::Git", Object.new)
|
10
|
+
stub_const("Vito::Recipes::Rbenv", Object.new)
|
11
|
+
stub_const("Vito::OperatingSystem", Object.new)
|
12
|
+
stub_const("Vito::Output", Object.new)
|
13
|
+
Vito::Output.stub(:write)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#run" do
|
17
|
+
it "installs the operating system dependencies" do
|
18
|
+
subject.stub(:install_git)
|
19
|
+
subject.stub(:install_rbenv)
|
20
|
+
|
21
|
+
dependencies = %w( build-essential openssl libreadline6
|
22
|
+
libreadline6-dev zlib1g zlib1g-dev libssl-dev
|
23
|
+
libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3
|
24
|
+
libxml2-dev libxslt1-dev autoconf libc6-dev
|
25
|
+
libncurses5-dev)
|
26
|
+
operating_system = double
|
27
|
+
operating_system.should_receive(:install_dependencies).with(dependencies)
|
28
|
+
Vito::OperatingSystem.stub(:new).with(subject) { operating_system }
|
29
|
+
subject.run
|
30
|
+
end
|
31
|
+
|
32
|
+
it "installs git" do
|
33
|
+
subject.stub(:install_rbenv)
|
34
|
+
subject.stub(:install_os_dependencies)
|
35
|
+
|
36
|
+
git = double
|
37
|
+
git.should_receive(:run)
|
38
|
+
Vito::Recipes::Git.stub(:new).with(subject) { git }
|
39
|
+
subject.run
|
40
|
+
end
|
41
|
+
|
42
|
+
it "installs rbenv" do
|
43
|
+
subject.stub(:install_git)
|
44
|
+
subject.stub(:install_os_dependencies)
|
45
|
+
|
46
|
+
rbenv = double
|
47
|
+
rbenv.should_receive(:run)
|
48
|
+
Vito::Recipes::Rbenv.stub(:new).with(subject) { rbenv }
|
49
|
+
subject.run
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "vito/shell_initializer"
|
2
|
+
require "contracts/vito/installation_contract"
|
3
|
+
|
4
|
+
describe Vito::ShellInitializer do
|
5
|
+
it_behaves_like "installation contract"
|
6
|
+
|
7
|
+
subject { Vito::ShellInitializer.new(["fixtures/vito.rb"]) }
|
8
|
+
|
9
|
+
describe "#run" do
|
10
|
+
let(:recipes) { double }
|
11
|
+
|
12
|
+
before do
|
13
|
+
stub_const("Vito::Ssh", Object.new)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "the execution starts" do
|
17
|
+
let(:ssh) { double }
|
18
|
+
let(:ssh_config) { double(ssh_host: :host, ssh_user: :user) }
|
19
|
+
|
20
|
+
it "connects to the SSH server" do
|
21
|
+
subject.stub(:config) { ssh_config }
|
22
|
+
subject.stub(:install_recipes)
|
23
|
+
subject.stub(:finish_execution)
|
24
|
+
Vito::Ssh.stub(:new).with(:host, :user) { ssh }
|
25
|
+
subject.run
|
26
|
+
subject.ssh.should == ssh
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "installation" do
|
31
|
+
it "installs the recipes" do
|
32
|
+
subject.stub(:start_execution)
|
33
|
+
subject.stub(:finish_execution)
|
34
|
+
|
35
|
+
Vito::Installation.stub(:new).with(subject) { recipes }
|
36
|
+
recipes.should_receive(:install)
|
37
|
+
|
38
|
+
subject.run
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "the execution ends" do
|
43
|
+
let(:ssh) { double }
|
44
|
+
|
45
|
+
it "closes the SSH connection" do
|
46
|
+
subject.stub(:ssh) { ssh }
|
47
|
+
subject.stub(:install_recipes)
|
48
|
+
subject.stub(:open_ssh_connection)
|
49
|
+
|
50
|
+
ssh.should_receive(:close)
|
51
|
+
subject.run
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#config" do
|
57
|
+
it "returns a configuration object" do
|
58
|
+
stub_const("Vito::RecipesConfiguration", Object.new)
|
59
|
+
Vito::RecipesConfiguration.should_receive(:new) { :config }
|
60
|
+
subject.config.should == :config
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "vito/utils/program_version"
|
2
|
+
|
3
|
+
describe Vito::Utils::ProgramVersion do
|
4
|
+
let(:connection) { double(query: output) }
|
5
|
+
|
6
|
+
subject { described_class.new("ruby -v", connection) }
|
7
|
+
|
8
|
+
describe "#matches?" do
|
9
|
+
context "the program exists" do
|
10
|
+
let(:output) do
|
11
|
+
double(success?: true,
|
12
|
+
result: "ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.2.0]")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns true if it matches" do
|
16
|
+
subject.matches?("2.0.0-p195").should be_true
|
17
|
+
subject.matches?("2.0.0p195").should be_true
|
18
|
+
subject.matches?("2.0.0").should be_true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns false if it doesn't matche" do
|
22
|
+
subject.matches?("2.0.0p125").should be_false
|
23
|
+
subject.matches?("1.9.3").should be_false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "the program doesn't exist" do
|
28
|
+
let(:output) do
|
29
|
+
double(success?: false,
|
30
|
+
result: "ruby 2.0.0p195 fake result")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns true if it matches" do
|
34
|
+
subject.matches?("2.0.0p195").should be_false
|
35
|
+
subject.matches?("2.0.0").should be_false
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns false if it doesn't matche" do
|
39
|
+
subject.matches?("2.0.0p125").should be_false
|
40
|
+
subject.matches?("1.9.3").should be_false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/vito.gemspec
CHANGED
@@ -4,16 +4,19 @@ require File.expand_path('../lib/vito/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Alexandre de Oliveira"]
|
6
6
|
gem.email = ["chavedomundo@gmail.com"]
|
7
|
-
gem.description = %q{
|
8
|
-
gem.summary = %q{
|
9
|
-
gem.homepage = ""
|
7
|
+
gem.description = %q{Vito installs webservers for you very easily. Its goal is to be opinionated, with a shallow learning curve needed due to the use of a Gemfile-like specification file.}
|
8
|
+
gem.summary = %q{Install webserver environments automatically in an easier way}
|
9
|
+
gem.homepage = "http://github.com/kurko/vito"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
14
|
gem.name = "vito"
|
15
|
+
gem.license = "MIT"
|
15
16
|
gem.require_paths = ["lib"]
|
16
17
|
gem.version = Vito::VERSION
|
17
18
|
|
19
|
+
gem.add_dependency("active_support")
|
18
20
|
gem.add_development_dependency("rspec")
|
21
|
+
gem.add_development_dependency("pry-debugger")
|
19
22
|
end
|
data/vito.rb
ADDED
metadata
CHANGED
@@ -1,69 +1,141 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vito
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Alexandre de Oliveira
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-07-13 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: active_support
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
14
27
|
- !ruby/object:Gem::Dependency
|
15
28
|
name: rspec
|
16
29
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
30
|
requirements:
|
19
|
-
- -
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-debugger
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
20
46
|
- !ruby/object:Gem::Version
|
21
47
|
version: '0'
|
22
48
|
type: :development
|
23
49
|
prerelease: false
|
24
50
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
51
|
requirements:
|
27
|
-
- -
|
52
|
+
- - '>='
|
28
53
|
- !ruby/object:Gem::Version
|
29
54
|
version: '0'
|
30
|
-
description:
|
55
|
+
description: Vito installs webservers for you very easily. Its goal is to be opinionated,
|
56
|
+
with a shallow learning curve needed due to the use of a Gemfile-like specification
|
57
|
+
file.
|
31
58
|
email:
|
32
59
|
- chavedomundo@gmail.com
|
33
|
-
executables:
|
60
|
+
executables:
|
61
|
+
- vito
|
34
62
|
extensions: []
|
35
63
|
extra_rdoc_files: []
|
36
64
|
files:
|
37
65
|
- .gitignore
|
66
|
+
- .rspec
|
38
67
|
- Gemfile
|
39
68
|
- LICENSE
|
40
69
|
- README.md
|
41
70
|
- Rakefile
|
71
|
+
- Vagrantfile
|
72
|
+
- bin/vito
|
42
73
|
- lib/vito.rb
|
74
|
+
- lib/vito/connection.rb
|
75
|
+
- lib/vito/installation.rb
|
76
|
+
- lib/vito/log.rb
|
77
|
+
- lib/vito/logger.rb
|
78
|
+
- lib/vito/operating_system.rb
|
79
|
+
- lib/vito/recipe.rb
|
80
|
+
- lib/vito/recipes/git.rb
|
81
|
+
- lib/vito/recipes/rbenv.rb
|
82
|
+
- lib/vito/recipes/ruby.rb
|
83
|
+
- lib/vito/recipes_configuration.rb
|
84
|
+
- lib/vito/server.rb
|
85
|
+
- lib/vito/shell_initializer.rb
|
86
|
+
- lib/vito/ssh.rb
|
87
|
+
- lib/vito/utils/program_version.rb
|
43
88
|
- lib/vito/version.rb
|
89
|
+
- spec/contracts/vito/installation_contract.rb
|
90
|
+
- spec/fixtures/vito.rb
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
- spec/vito/connection_spec.rb
|
93
|
+
- spec/vito/installation_spec.rb
|
94
|
+
- spec/vito/log_spec.rb
|
95
|
+
- spec/vito/output_spec.rb
|
96
|
+
- spec/vito/recipes/git_spec.rb
|
97
|
+
- spec/vito/recipes/ruby_spec.rb
|
98
|
+
- spec/vito/recipes_configuration_spec.rb
|
99
|
+
- spec/vito/recipes_spec.rb
|
100
|
+
- spec/vito/shell_initializer_spec.rb
|
101
|
+
- spec/vito/utils/program_version_spec.rb
|
44
102
|
- vito.gemspec
|
45
|
-
|
46
|
-
|
103
|
+
- vito.rb
|
104
|
+
homepage: http://github.com/kurko/vito
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
47
108
|
post_install_message:
|
48
109
|
rdoc_options: []
|
49
110
|
require_paths:
|
50
111
|
- lib
|
51
112
|
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
113
|
requirements:
|
54
|
-
- -
|
114
|
+
- - '>='
|
55
115
|
- !ruby/object:Gem::Version
|
56
116
|
version: '0'
|
57
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
118
|
requirements:
|
60
|
-
- -
|
119
|
+
- - '>='
|
61
120
|
- !ruby/object:Gem::Version
|
62
121
|
version: '0'
|
63
122
|
requirements: []
|
64
123
|
rubyforge_project:
|
65
|
-
rubygems_version:
|
124
|
+
rubygems_version: 2.0.4
|
66
125
|
signing_key:
|
67
|
-
specification_version:
|
68
|
-
summary:
|
69
|
-
test_files:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Install webserver environments automatically in an easier way
|
128
|
+
test_files:
|
129
|
+
- spec/contracts/vito/installation_contract.rb
|
130
|
+
- spec/fixtures/vito.rb
|
131
|
+
- spec/spec_helper.rb
|
132
|
+
- spec/vito/connection_spec.rb
|
133
|
+
- spec/vito/installation_spec.rb
|
134
|
+
- spec/vito/log_spec.rb
|
135
|
+
- spec/vito/output_spec.rb
|
136
|
+
- spec/vito/recipes/git_spec.rb
|
137
|
+
- spec/vito/recipes/ruby_spec.rb
|
138
|
+
- spec/vito/recipes_configuration_spec.rb
|
139
|
+
- spec/vito/recipes_spec.rb
|
140
|
+
- spec/vito/shell_initializer_spec.rb
|
141
|
+
- spec/vito/utils/program_version_spec.rb
|