ober 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Gemfile.lock +18 -0
- data/LICENSE +23 -0
- data/README +15 -0
- data/bin/ober +6 -0
- data/doc/sample.rb +13 -0
- data/lib/ober/application.rb +21 -0
- data/lib/ober/cli.rb +17 -0
- data/lib/ober/configuration.rb +79 -0
- data/lib/ober/installer.rb +83 -0
- data/lib/ober/runner/rvm.rb +50 -0
- data/lib/ober/runner.rb +38 -0
- data/lib/ober/version.rb +3 -0
- data/lib/ober.rb +1 -0
- metadata +96 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2013 Kaspar Schiess
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person
|
5
|
+
obtaining a copy of this software and associated documentation
|
6
|
+
files (the "Software"), to deal in the Software without
|
7
|
+
restriction, including without limitation the rights to use,
|
8
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the
|
10
|
+
Software is furnished to do so, subject to the following
|
11
|
+
conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
ober - a small application installer for Ruby
|
3
|
+
|
4
|
+
SYNOPSIS
|
5
|
+
|
6
|
+
...
|
7
|
+
|
8
|
+
STATUS
|
9
|
+
|
10
|
+
This is early alpha. Where applications do what one programmer wants, not
|
11
|
+
what other programmers want.
|
12
|
+
|
13
|
+
LICENSE
|
14
|
+
|
15
|
+
see LICENSE file, (c) 2013 Kaspar Schiess
|
data/bin/ober
ADDED
data/doc/sample.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
require 'ober/configuration'
|
3
|
+
require 'ober/installer'
|
4
|
+
|
5
|
+
module Ober
|
6
|
+
# The main application class, presents all operations as methods and
|
7
|
+
# has no connection to the CLI interface.
|
8
|
+
#
|
9
|
+
class Application
|
10
|
+
def install env
|
11
|
+
config = read_configuration
|
12
|
+
environment = config.environment(env)
|
13
|
+
Installer.new(environment).install
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_configuration
|
17
|
+
source = File.read('ober_menu.rb')
|
18
|
+
Configuration.parse(source, 'ober_menu.rb')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/ober/cli.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require 'clamp'
|
3
|
+
require 'ober/application'
|
4
|
+
|
5
|
+
module Ober
|
6
|
+
class CLI < Clamp::Command
|
7
|
+
subcommand('install',
|
8
|
+
"Installs applications from ENV to this machine.") do
|
9
|
+
|
10
|
+
parameter 'ENV', 'environment to install'
|
11
|
+
|
12
|
+
def execute
|
13
|
+
Application.new.install(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Ober
|
2
|
+
|
3
|
+
# Ober configuration, which is read from a file called 'ober_menu' or
|
4
|
+
# from stdin. The configuration is a Ruby DSL. Check out child classes
|
5
|
+
# of the configuration for understanding the DSL.
|
6
|
+
#
|
7
|
+
class Configuration
|
8
|
+
# Largest context of evaluation. This is mostly going to be the file
|
9
|
+
# scope.
|
10
|
+
#
|
11
|
+
class Source
|
12
|
+
def initialize config
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def environment env, &block
|
17
|
+
@config.environment(env).instance_eval(&block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# A server environment.
|
22
|
+
#
|
23
|
+
class Environment
|
24
|
+
def initialize name
|
25
|
+
@applications = Hash.new { |h,k| h[k] = Application.new(k) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def app name, &block
|
29
|
+
@applications[name].instance_eval(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def apps
|
33
|
+
@applications.values
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# An application that is installed.
|
38
|
+
#
|
39
|
+
class Application
|
40
|
+
attr_reader :name
|
41
|
+
|
42
|
+
def initialize name
|
43
|
+
@name = name
|
44
|
+
end
|
45
|
+
|
46
|
+
def root path=nil
|
47
|
+
@root ||= path
|
48
|
+
end
|
49
|
+
|
50
|
+
def rvm version=nil
|
51
|
+
@rvm ||= version
|
52
|
+
end
|
53
|
+
|
54
|
+
def git url=nil, opts={}
|
55
|
+
@git ||= [url, opts]
|
56
|
+
end
|
57
|
+
|
58
|
+
def user name=nil
|
59
|
+
@user ||= name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.parse *args
|
64
|
+
new.tap { |o| o.parse(*args) }
|
65
|
+
end
|
66
|
+
def parse source, file_name
|
67
|
+
context = Source.new(self)
|
68
|
+
context.instance_eval { binding.eval(source, file_name) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def initialize
|
72
|
+
@environments = Hash.new { |h,k| h[k] = Environment.new(k) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def environment env
|
76
|
+
@environments[env.to_sym]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
require 'ober/runner'
|
6
|
+
require 'ober/runner/rvm'
|
7
|
+
|
8
|
+
module Ober
|
9
|
+
class Installer
|
10
|
+
def initialize environment
|
11
|
+
@environment = environment
|
12
|
+
end
|
13
|
+
|
14
|
+
def install
|
15
|
+
@environment.apps.each do |app|
|
16
|
+
puts "Installing app #{app.name}..."
|
17
|
+
install_app app
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def runner
|
22
|
+
Runner.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def install_app app
|
26
|
+
validate_app app
|
27
|
+
|
28
|
+
# This rather nasty trick ensures that other users can use our
|
29
|
+
# ssh agent forwarding too. Allows for git checkouts but also take
|
30
|
+
# over of all your base.
|
31
|
+
if ENV['SSH_CONNECTION'] && ENV['SSH_AUTH_SOCK']
|
32
|
+
puts "Opening up your ssh connection forwarding to all users on this machine."
|
33
|
+
puts "WARNING: This is a bad thing on multi user machines. Don't use this tool"
|
34
|
+
puts "in such an environment."
|
35
|
+
puts
|
36
|
+
ssh_auth_sock = ENV['SSH_AUTH_SOCK']
|
37
|
+
FileUtils.chmod(0777, File.dirname(ssh_auth_sock))
|
38
|
+
FileUtils.chmod(0666, ssh_auth_sock)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Makes sure the directory exists
|
42
|
+
root = Pathname.new(app.root)
|
43
|
+
unless root.directory?
|
44
|
+
FileUtils.mkdir_p(root)
|
45
|
+
FileUtils.chown(app.user, nil, root) if app.user
|
46
|
+
end
|
47
|
+
|
48
|
+
# Installs the git source code and resets to the given version
|
49
|
+
if app.git
|
50
|
+
url, options = app.git
|
51
|
+
|
52
|
+
git_clone app, url, options[:version] || 'master'
|
53
|
+
end
|
54
|
+
|
55
|
+
# If we need to use RVM, create another object that takes care of
|
56
|
+
# running things for us.
|
57
|
+
r = runner
|
58
|
+
if app.rvm
|
59
|
+
r = Runner::RVM.new(app.rvm)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Makes sure all the gems are installed
|
63
|
+
r.run 'bundle install --deployment', cwd: app.root, user: app.user
|
64
|
+
end
|
65
|
+
|
66
|
+
def git_clone app, source, version
|
67
|
+
opts = { user: app.user, cwd: app.root }
|
68
|
+
runner.run "git clone #{source} .", opts do |ex|
|
69
|
+
raise ex unless ex.to_s.match(%r(fatal: destination path '.' already exists))
|
70
|
+
"Already exists, error ignored."
|
71
|
+
end
|
72
|
+
|
73
|
+
runner.run "git fetch #{source}", opts
|
74
|
+
runner.run "git reset --hard #{version}", opts
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_app app
|
78
|
+
fail 'Application has no root. Please set one: root "some/path"' unless
|
79
|
+
app.root
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module Ober
|
3
|
+
class Runner
|
4
|
+
class RVM < Runner
|
5
|
+
def initialize rvm
|
6
|
+
@rvm_source_path = source(rvm)
|
7
|
+
fail "No such RVM version. (#{rvm} not found)" unless @rvm_source_path
|
8
|
+
|
9
|
+
detect_environment_for_rvm
|
10
|
+
end
|
11
|
+
|
12
|
+
def variables
|
13
|
+
%w(PATH rvm_env_string rvm_path rvm_ruby_string rvm_gemset_name
|
14
|
+
RUBY_VERSION GEM_HOME GEM_PATH MY_RUBY_HOME IRBRC MAGLEV_HOME RBXOPT)
|
15
|
+
end
|
16
|
+
def detect_environment_for_rvm
|
17
|
+
echo_string = ''
|
18
|
+
variables.each { |v| echo_string << "echo $#{v}; " }
|
19
|
+
|
20
|
+
output = run_silent(%Q(
|
21
|
+
bash -c 'source #{@rvm_source_path}; #{echo_string}'
|
22
|
+
).strip)
|
23
|
+
|
24
|
+
@env = {}
|
25
|
+
variables.zip(output.lines).each do |var, val|
|
26
|
+
val.chomp!
|
27
|
+
@env[var] = val.size == 0 ? nil : val
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def produce_shellout cmd, opts
|
32
|
+
Mixlib::ShellOut.new(cmd, opts.merge(environment: @env))
|
33
|
+
end
|
34
|
+
|
35
|
+
# You should find version by running
|
36
|
+
#
|
37
|
+
# rvm env --path
|
38
|
+
#
|
39
|
+
# and taking the last part of the path as your version. Unlike what
|
40
|
+
# rvm accepts, we're kind of picky here.
|
41
|
+
#
|
42
|
+
def source version
|
43
|
+
# Locate rvm installation:
|
44
|
+
["#{ENV['HOME']}/.rvm/environments"].
|
45
|
+
map { |path| File.join(path, version) }.
|
46
|
+
find { |path| File.exist?(path) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/ober/runner.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
require 'mixlib/shellout'
|
3
|
+
|
4
|
+
module Ober
|
5
|
+
class Runner
|
6
|
+
def produce_shellout cmd, opts
|
7
|
+
Mixlib::ShellOut.new(cmd, opts)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run cmd, opts={}, &block
|
11
|
+
puts " $ #{cmd}"
|
12
|
+
output = run_silent(cmd, opts, &block)
|
13
|
+
|
14
|
+
if output
|
15
|
+
output.lines.each do |line|
|
16
|
+
puts " > #{line.chomp}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
output
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_silent cmd, opts={}
|
24
|
+
shellout = produce_shellout(cmd, opts)
|
25
|
+
shellout.run_command
|
26
|
+
|
27
|
+
shellout.error!
|
28
|
+
|
29
|
+
shellout.stdout
|
30
|
+
rescue Mixlib::ShellOut::ShellCommandFailed => ex
|
31
|
+
if block_given?
|
32
|
+
return yield(ex)
|
33
|
+
else
|
34
|
+
raise ex
|
35
|
+
end
|
36
|
+
end # def run
|
37
|
+
end # class Runner
|
38
|
+
end
|
data/lib/ober/version.rb
ADDED
data/lib/ober.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ober/cli'
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ober
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kaspar Schiess
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-11-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: clamp
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>'
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>'
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mixlib-shellout
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>'
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>'
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.0'
|
46
|
+
description: ! "Provides an alternative to the various remote applications that fulfill
|
47
|
+
the same\npurpose, such as capistrano or even chef. Installs Ruby applications to
|
48
|
+
servers\non defined locations. \n\nVery early alpha. This will eventually deal with
|
49
|
+
all the intricacies of bundler, \nRVM and rbenv, but for now, does really simple
|
50
|
+
installations. \n"
|
51
|
+
email: kaspar.schiess@absurd.li
|
52
|
+
executables:
|
53
|
+
- ober
|
54
|
+
extensions: []
|
55
|
+
extra_rdoc_files: []
|
56
|
+
files:
|
57
|
+
- Gemfile
|
58
|
+
- Gemfile.lock
|
59
|
+
- LICENSE
|
60
|
+
- README
|
61
|
+
- bin/ober
|
62
|
+
- doc/sample.rb
|
63
|
+
- lib/ober.rb
|
64
|
+
- lib/ober/application.rb
|
65
|
+
- lib/ober/cli.rb
|
66
|
+
- lib/ober/configuration.rb
|
67
|
+
- lib/ober/installer.rb
|
68
|
+
- lib/ober/runner.rb
|
69
|
+
- lib/ober/runner/rvm.rb
|
70
|
+
- lib/ober/version.rb
|
71
|
+
homepage: https://bitbucket.org/kschiess/ober
|
72
|
+
licenses: []
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.25
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Ober serves applications to servers.
|
95
|
+
test_files: []
|
96
|
+
has_rdoc:
|