servitor 0.0.1
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.
- data/.gitignore +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +105 -0
- data/LICENSE +19 -0
- data/README.md +102 -0
- data/lib/cli/cli.rb +96 -0
- data/lib/configuration/configuration.rb +2 -0
- data/lib/configuration/configuration_resolver.rb +97 -0
- data/lib/configuration/yaml_configuration_provider.rb +28 -0
- data/lib/control/control.rb +0 -0
- data/lib/deployment/bundle_deployer.rb +14 -0
- data/lib/deployment/deployment.rb +2 -0
- data/lib/deployment/envdir_deployer.rb +34 -0
- data/lib/helpers/child_process_helper.rb +41 -0
- data/lib/helpers/helpers.rb +1 -0
- data/lib/infrastructure/infrastructure.rb +16 -0
- data/lib/infrastructure/infrastructure_provisioner.rb +25 -0
- data/lib/infrastructure/infrastructure_requirements.rb +25 -0
- data/lib/provisioners/Vagrantfile.erb +16 -0
- data/lib/provisioners/provisioners.rb +6 -0
- data/lib/provisioners/ssh_key.rb +22 -0
- data/lib/provisioners/vagrant_box.rb +116 -0
- data/lib/provisioners/vagrant_box_provisioner.rb +37 -0
- data/lib/provisioners/vagrant_box_ruby_installer.rb +34 -0
- data/lib/provisioners/vagrantfile.rb +34 -0
- data/lib/provisioners/veewee_box.rb +91 -0
- data/lib/resource/mysql_resource.rb +33 -0
- data/lib/resource/resource.rb +1 -0
- data/lib/service/service.rb +12 -0
- data/lib/service/service_definition/Servicefile.erb +54 -0
- data/lib/service/service_definition/deployment_stages.rb +16 -0
- data/lib/service/service_definition/resource_configuration.rb +14 -0
- data/lib/service/service_definition/service_configuration.rb +19 -0
- data/lib/service/service_definition/service_definition.rb +49 -0
- data/lib/service/service_definition/variable.rb +22 -0
- data/lib/service/service_file_parser.rb +21 -0
- data/lib/service/service_graph/service_graph.rb +58 -0
- data/lib/service/service_graph/service_graph_flattener.rb +34 -0
- data/lib/service/service_graph/service_graph_node.rb +15 -0
- data/lib/service/service_linker.rb +56 -0
- data/lib/service/service_locator.rb +43 -0
- data/lib/servitor.rb +47 -0
- data/servitor.gemspec +18 -0
- data/spec/provisioners/vagrant_basebox_provisioner_spec.rb +63 -0
- data/spec/provisioners/vagrant_box_ruby_provisioner_spec.rb +48 -0
- data/spec/spec_helper.rb +7 -0
- metadata +171 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
module Servitor
|
2
|
+
|
3
|
+
class ServiceGraphNode
|
4
|
+
|
5
|
+
attr_reader :depends_on_nodes, :depended_on_by_nodes, :service_definition
|
6
|
+
|
7
|
+
def initialize(service_definition)
|
8
|
+
@service_definition = service_definition
|
9
|
+
@depends_on_nodes = []
|
10
|
+
@depended_on_by_nodes = []
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Servitor
|
2
|
+
class ServiceLinker
|
3
|
+
|
4
|
+
attr_reader :service_nodes, :service_box_names
|
5
|
+
|
6
|
+
def initialize(service_nodes, service_box_names)
|
7
|
+
@service_nodes = service_nodes
|
8
|
+
@service_box_names = service_box_names
|
9
|
+
end
|
10
|
+
|
11
|
+
# Transforms the list of service nodes to a list of services. Service nodes
|
12
|
+
# describe the requirements and dependencies of each app, while services describe
|
13
|
+
# the VMs that satisfy those requirements and dependencies.
|
14
|
+
def link(options={})
|
15
|
+
next_ip = (options[:first_ip] || 2).to_i
|
16
|
+
next_port = (options[:first_port] || 3000).to_i
|
17
|
+
@service_nodes.map do |service_node|
|
18
|
+
service = Service.new
|
19
|
+
service.service_node = service_node
|
20
|
+
service.name = service_node.service_definition.name
|
21
|
+
service.box = @service_box_names[service_node]
|
22
|
+
service.ip_address = ip_address(next_ip, options)
|
23
|
+
begin
|
24
|
+
next_ip += 1
|
25
|
+
end while ip_address(next_ip, options) == host_ip(options)
|
26
|
+
service.forwarded_ports = { 80 => next_port }.merge(ports_for(service_node))
|
27
|
+
next_port += 1
|
28
|
+
service.root = service_node.service_definition.service_root
|
29
|
+
service.vm_root = options[:vm_root] || '/mnt/app/current'
|
30
|
+
service
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def ports_for(service_node)
|
37
|
+
ports = {}
|
38
|
+
if service_node.service_definition.configuration.resources.any? {|r| r.options[:type] == 'mysql'}
|
39
|
+
# ports[3306] = 3306
|
40
|
+
end
|
41
|
+
ports
|
42
|
+
end
|
43
|
+
|
44
|
+
def ip_block(options)
|
45
|
+
options[:ip_block] || '192.168.51'
|
46
|
+
end
|
47
|
+
|
48
|
+
def ip_address(next_ip, options)
|
49
|
+
"#{ip_block(options)}.#{next_ip}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def host_ip(options)
|
53
|
+
"#{ip_block(options)}.1"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Servitor
|
2
|
+
|
3
|
+
class ServiceLocator
|
4
|
+
|
5
|
+
FILENAMES = %w(Servicefile .servicefile)
|
6
|
+
DEFAULT_SERVICES_DIR = ENV['SERVITOR_SERVICES_DIR'] || File.join(ENV['HOME'],'git')
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
attr_writer :services_dir
|
11
|
+
|
12
|
+
def services_dir
|
13
|
+
@services_dir || DEFAULT_SERVICES_DIR
|
14
|
+
end
|
15
|
+
|
16
|
+
# Locates the local service or a named service, returning a service config
|
17
|
+
def locate(service_name = nil)
|
18
|
+
if service_name
|
19
|
+
dir = File.join(services_dir, service_name)
|
20
|
+
else
|
21
|
+
dir = Dir.pwd
|
22
|
+
end
|
23
|
+
file = service_file_in_dir(dir)
|
24
|
+
ServiceFileParser.parse(file, dir)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def service_file_in_dir(dir)
|
30
|
+
file_names = FILENAMES + FILENAMES.map { |f| File.join('config', f) }
|
31
|
+
file_names.each do |file_name|
|
32
|
+
service_file_name = File.join(dir, file_name)
|
33
|
+
return service_file_name if File.exists?(service_file_name)
|
34
|
+
end
|
35
|
+
raise "No service file found in #{dir}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/servitor.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module ServitorRequire
|
2
|
+
# for 1.8 compatibility
|
3
|
+
def servitor_require(path)
|
4
|
+
require(File.join(File.dirname(caller[0]), path))
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
extend(ServitorRequire)
|
9
|
+
|
10
|
+
servitor_require 'helpers/helpers'
|
11
|
+
servitor_require 'cli/cli'
|
12
|
+
servitor_require 'configuration/configuration'
|
13
|
+
servitor_require 'control/control'
|
14
|
+
servitor_require 'deployment/deployment'
|
15
|
+
servitor_require 'infrastructure/infrastructure'
|
16
|
+
servitor_require 'provisioners/provisioners'
|
17
|
+
servitor_require 'resource/resource'
|
18
|
+
servitor_require 'service/service'
|
19
|
+
|
20
|
+
module Servitor
|
21
|
+
def self.root
|
22
|
+
@root
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.root=(path)
|
26
|
+
raise ServitorRootException, 'Servitor root has already been set; it can only be set once.' if @root
|
27
|
+
@root = path
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.data_root
|
31
|
+
File.join(Servitor.root, '.servitor')
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.boxes_root
|
35
|
+
File.join(Servitor.data_root, 'boxes')
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.vagrantfile
|
39
|
+
File.join(Servitor.data_root, 'Vagrantfile')
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.ssh_dir
|
43
|
+
File.join(Servitor.data_root, 'ssh')
|
44
|
+
end
|
45
|
+
|
46
|
+
class ServitorRootException < StandardError; end
|
47
|
+
end
|
data/servitor.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'servitor'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2012-11-02'
|
5
|
+
s.summary = "A tool to help compose an SOA from 12-factor apps"
|
6
|
+
s.description = "A tool to help compose an SOA from 12-factor apps"
|
7
|
+
s.authors = ["Harry Wilkinson"]
|
8
|
+
s.email = 'hwilkinson@mdsol.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
11
|
+
s.homepage = 'http://github.com/harryw/servitor'
|
12
|
+
|
13
|
+
s.add_dependency 'veewee', '0.3.0.beta2'
|
14
|
+
s.add_dependency 'childprocess'
|
15
|
+
s.add_dependency 'erubis'
|
16
|
+
s.add_dependency 'mysql2'
|
17
|
+
s.add_development_dependency 'rspec'
|
18
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Servitor::VagrantBaseboxProvisioner do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@requirements = Servitor::InfrastructureRequirements.new
|
7
|
+
@requirements.os_name 'ubuntu'
|
8
|
+
@requirements.os_version '10.04'
|
9
|
+
@requirements.os_arch '64'
|
10
|
+
@provisioner = Servitor::VagrantBaseboxProvisioner.new(@requirements)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#name' do
|
14
|
+
it 'contains the os name and version' do
|
15
|
+
@provisioner.name.should == "#{@requirements.os_name}-#{@requirements.os_version}".gsub(/[^a-zA-Z0-9\-]/, '-')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#provision' do
|
20
|
+
|
21
|
+
# The result of a #provision call is that there is a base box available satisfying the specified requirements.
|
22
|
+
# So, to test #provision we need to build a new box from that base and inspect it.
|
23
|
+
|
24
|
+
before :all do
|
25
|
+
@pwd = Dir.pwd
|
26
|
+
@provisioner.provision
|
27
|
+
@box = Servitor::VagrantBox.new('VagrantBaseBoxProvisionerTest')
|
28
|
+
@tmpdir = File.join(@pwd, 'VagrantBaseBoxProvisionerTest')
|
29
|
+
FileUtils.mkdir_p @tmpdir
|
30
|
+
FileUtils.cd @tmpdir
|
31
|
+
@box.init(@provisioner.name)
|
32
|
+
@box.up
|
33
|
+
end
|
34
|
+
|
35
|
+
after :all do
|
36
|
+
@box.destroy
|
37
|
+
FileUtils.cd @pwd
|
38
|
+
FileUtils.rm_rf @tmpdir
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'has the requested OS' do
|
42
|
+
@box.ssh('lsb_release -si', :capture => true).should =~ Regexp.new(@requirements.os_name, true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'has the requested OS version' do
|
46
|
+
@box.ssh('lsb_release -sr', :capture => true).should =~ Regexp.new(@requirements.os_version, true)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'has the requested OS architecture' do
|
50
|
+
arch = case @requirements.os_arch
|
51
|
+
when /64/
|
52
|
+
'64'
|
53
|
+
when /32/, /86/
|
54
|
+
'32'
|
55
|
+
else
|
56
|
+
raise "unrecognized architecture: #{@requirements.os_arch}"
|
57
|
+
end
|
58
|
+
@box.ssh("uname -m | sed 's/x86_//;s/i[3-6]86/32/'", :capture => true).should =~ Regexp.new(arch)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Servitor::VagrantBoxRubyProvisioner do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@requirements = Servitor::InfrastructureRequirements.new
|
7
|
+
@requirements.os_name 'ubuntu'
|
8
|
+
@requirements.os_version '10.04'
|
9
|
+
@requirements.os_arch '64'
|
10
|
+
@requirements.ruby_version '1.9.2'
|
11
|
+
@provisioner = Servitor::VagrantBoxRubyProvisioner.new(@requirements)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#name' do
|
15
|
+
it 'contains the ruby version' do
|
16
|
+
@provisioner.name.should == "#{@requirements.os_name}-#{@requirements.os_version}-ruby-#{@requirements.ruby_version}".gsub(/[^a-zA-Z0-9\-]/, '-')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#provision' do
|
21
|
+
|
22
|
+
# The result of a #provision call is that there is a base box available satisfying the specified requirements.
|
23
|
+
# So, to test #provision we need to build a new box from that base and inspect it.
|
24
|
+
|
25
|
+
before :all do
|
26
|
+
@pwd = Dir.pwd
|
27
|
+
@provisioner.provision
|
28
|
+
@box = Servitor::VagrantBox.new('VagrantBoxRubyProvisionerTest')
|
29
|
+
@tmpdir = File.join(@pwd, 'VagrantBoxRubyProvisionerTest')
|
30
|
+
FileUtils.mkdir_p @tmpdir
|
31
|
+
FileUtils.cd @tmpdir
|
32
|
+
@box.init(@provisioner.name)
|
33
|
+
@box.up
|
34
|
+
end
|
35
|
+
|
36
|
+
after :all do
|
37
|
+
@box.destroy
|
38
|
+
FileUtils.cd @pwd
|
39
|
+
FileUtils.rm_rf @tmpdir
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'uses the requested ruby version' do
|
43
|
+
@box.ssh('ruby --version', :capture => true).should =~ Regexp.new(@requirements.ruby_version, true)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: servitor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Harry Wilkinson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: veewee
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.3.0.beta2
|
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.3.0.beta2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: childprocess
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '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'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: erubis
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: mysql2
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: A tool to help compose an SOA from 12-factor apps
|
95
|
+
email: hwilkinson@mdsol.com
|
96
|
+
executables: []
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files: []
|
99
|
+
files:
|
100
|
+
- .gitignore
|
101
|
+
- Gemfile
|
102
|
+
- Gemfile.lock
|
103
|
+
- LICENSE
|
104
|
+
- README.md
|
105
|
+
- lib/cli/cli.rb
|
106
|
+
- lib/configuration/configuration.rb
|
107
|
+
- lib/configuration/configuration_resolver.rb
|
108
|
+
- lib/configuration/yaml_configuration_provider.rb
|
109
|
+
- lib/control/control.rb
|
110
|
+
- lib/deployment/bundle_deployer.rb
|
111
|
+
- lib/deployment/deployment.rb
|
112
|
+
- lib/deployment/envdir_deployer.rb
|
113
|
+
- lib/helpers/child_process_helper.rb
|
114
|
+
- lib/helpers/helpers.rb
|
115
|
+
- lib/infrastructure/infrastructure.rb
|
116
|
+
- lib/infrastructure/infrastructure_provisioner.rb
|
117
|
+
- lib/infrastructure/infrastructure_requirements.rb
|
118
|
+
- lib/provisioners/Vagrantfile.erb
|
119
|
+
- lib/provisioners/provisioners.rb
|
120
|
+
- lib/provisioners/ssh_key.rb
|
121
|
+
- lib/provisioners/vagrant_box.rb
|
122
|
+
- lib/provisioners/vagrant_box_provisioner.rb
|
123
|
+
- lib/provisioners/vagrant_box_ruby_installer.rb
|
124
|
+
- lib/provisioners/vagrantfile.rb
|
125
|
+
- lib/provisioners/veewee_box.rb
|
126
|
+
- lib/resource/mysql_resource.rb
|
127
|
+
- lib/resource/resource.rb
|
128
|
+
- lib/service/service.rb
|
129
|
+
- lib/service/service_definition/Servicefile.erb
|
130
|
+
- lib/service/service_definition/deployment_stages.rb
|
131
|
+
- lib/service/service_definition/resource_configuration.rb
|
132
|
+
- lib/service/service_definition/service_configuration.rb
|
133
|
+
- lib/service/service_definition/service_definition.rb
|
134
|
+
- lib/service/service_definition/variable.rb
|
135
|
+
- lib/service/service_file_parser.rb
|
136
|
+
- lib/service/service_graph/service_graph.rb
|
137
|
+
- lib/service/service_graph/service_graph_flattener.rb
|
138
|
+
- lib/service/service_graph/service_graph_node.rb
|
139
|
+
- lib/service/service_linker.rb
|
140
|
+
- lib/service/service_locator.rb
|
141
|
+
- lib/servitor.rb
|
142
|
+
- servitor.gemspec
|
143
|
+
- spec/provisioners/vagrant_basebox_provisioner_spec.rb
|
144
|
+
- spec/provisioners/vagrant_box_ruby_provisioner_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
homepage: http://github.com/harryw/servitor
|
147
|
+
licenses: []
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 1.8.24
|
167
|
+
signing_key:
|
168
|
+
specification_version: 3
|
169
|
+
summary: A tool to help compose an SOA from 12-factor apps
|
170
|
+
test_files: []
|
171
|
+
has_rdoc:
|