proctor 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/TODO +28 -0
- data/bin/proctor +55 -85
- data/bin/showlog +5 -0
- data/bin/showtime +5 -0
- data/lib/proctor/command/asset_list_cmd.rb +56 -0
- data/lib/proctor/{presenter/show.rb → command/asset_show_cmd.rb} +7 -2
- data/lib/proctor/command/file_cleanup_cmd.rb +81 -0
- data/lib/proctor/command/file_export_cmd.rb +79 -0
- data/lib/proctor/command/helpers/command.rb +27 -0
- data/lib/proctor/command/render_group_cmd.rb +39 -0
- data/lib/proctor/command/render_service_cmd.rb +34 -0
- data/lib/proctor/command/start_cmd.rb +70 -0
- data/lib/proctor/config/app_file.rb +54 -0
- data/lib/proctor/config/app_files.rb +50 -0
- data/lib/proctor/config/env.rb +35 -0
- data/lib/proctor/config/template_file.rb +41 -0
- data/lib/proctor/config/template_files.rb +39 -0
- data/lib/proctor/manager.rb +36 -3
- data/lib/proctor/managers.rb +38 -0
- data/lib/proctor/node.rb +26 -0
- data/lib/proctor/nodes.rb +38 -0
- data/lib/proctor/resource/erb.rb +95 -0
- data/lib/proctor/resource/lookup.rb +82 -0
- data/lib/proctor/service.rb +28 -3
- data/lib/proctor/services.rb +38 -0
- data/lib/proctor/util/helpers.rb +13 -0
- data/lib/proctor/util/version.rb +3 -0
- data/proctor.gemspec +2 -1
- data/proctor/Proctorfile +35 -34
- data/proctor/templates/foreman_default_g.erb +3 -0
- data/proctor/templates/monit_default_s.erb +3 -6
- data/proctor/templates/monit_faye_s.erb +3 -3
- data/proctor/templates/upstart_default_g.erb +1 -0
- data/proctor/templates/upstart_default_s.erb +1 -3
- data/proctor/templates/upstart_passenger_s.erb +3 -0
- data/spec/acceptance/asset_list_spec.rb +16 -0
- data/spec/acceptance/asset_show_spec.rb +16 -0
- data/spec/acceptance/file_cleanup_spec.rb +16 -0
- data/spec/acceptance/file_export_spec.rb +16 -0
- data/spec/acceptance/render_group_spec.rb +15 -0
- data/spec/acceptance/render_service_spec.rb +16 -0
- data/spec/acceptance/start_spec.rb +16 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/unit/command/file_export_cmd_spec.rb +46 -0
- data/spec/unit/command/file_list_cmd_spec.rb +30 -0
- data/spec/unit/command/render_group_cmd_spec.rb +44 -0
- data/spec/unit/command/render_service_cmd_spec.rb +42 -0
- data/spec/unit/{app_file_spec.rb → config/app_file_spec.rb} +27 -7
- data/spec/unit/config/app_files_spec.rb +55 -0
- data/spec/unit/config/env_spec.rb +37 -0
- data/spec/unit/config/template_file_spec.rb +55 -0
- data/spec/unit/config/template_files_spec.rb +32 -0
- data/spec/unit/manager_spec.rb +30 -10
- data/spec/unit/managers_spec.rb +40 -0
- data/spec/unit/node_spec.rb +34 -0
- data/spec/unit/nodes_spec.rb +36 -0
- data/spec/unit/service_spec.rb +31 -10
- data/spec/unit/services_spec.rb +34 -0
- metadata +86 -31
- data/Proctorfile +0 -4
- data/lib/proctor/app_config.rb +0 -23
- data/lib/proctor/app_file.rb +0 -44
- data/lib/proctor/cmd_state.rb +0 -39
- data/lib/proctor/presenter/list.rb +0 -67
- data/lib/proctor/presenter/render.rb +0 -39
- data/lib/proctor/template.rb +0 -5
- data/lib/proctor/template_config.rb +0 -22
- data/lib/proctor/template_file.rb +0 -44
- data/lib/proctor/util.rb +0 -12
- data/lib/proctor/version.rb +0 -3
- data/proctor/templates/foreman_default_n.erb +0 -9
- data/proctor/templates/monit_web_s.erb +0 -0
- data/proctor/templates/upstart_default_n.erb +0 -0
- data/spec/acceptance/help_spec.rb +0 -36
- data/spec/acceptance/list_spec.rb +0 -17
- data/spec/unit/app_config_spec.rb +0 -30
- data/spec/unit/template_config_spec.rb +0 -12
- data/spec/unit/template_file_spec.rb +0 -16
- data/spec/unit/template_spec.rb +0 -8
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative './manager'
|
2
|
+
|
3
|
+
module Proctor
|
4
|
+
class Managers
|
5
|
+
|
6
|
+
attr_reader :all, :app_files
|
7
|
+
|
8
|
+
def initialize(app_files, params)
|
9
|
+
@app_files = app_files
|
10
|
+
@params = params
|
11
|
+
@all = manager_list(app_files).map do |m|
|
12
|
+
Manager.new(*m)
|
13
|
+
end.sort {|a,b| a.name <=> b.name}
|
14
|
+
end
|
15
|
+
|
16
|
+
def names
|
17
|
+
@all.map {|m| m.name}.sort
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_name(name)
|
21
|
+
@all.find {|manager| manager.name == name}
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_by_handle(handle)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def manager_data(app_files)
|
30
|
+
app_files.merged_data['managers']
|
31
|
+
end
|
32
|
+
|
33
|
+
def manager_list(app_files)
|
34
|
+
manager_data(app_files).each_pair.map { |name, data| [name, data] }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/proctor/node.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative './util/helpers'
|
2
|
+
|
3
|
+
module Proctor
|
4
|
+
class Node
|
5
|
+
|
6
|
+
include Proctor::Util::Helpers
|
7
|
+
|
8
|
+
attr_reader :name, :data, :handle
|
9
|
+
|
10
|
+
def initialize(name, data)
|
11
|
+
@name = name
|
12
|
+
@data = data
|
13
|
+
@handle = md5_handle(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def services
|
17
|
+
@data
|
18
|
+
end
|
19
|
+
|
20
|
+
# check that node has at least one service
|
21
|
+
# check that each of the services is defined
|
22
|
+
# validate each service
|
23
|
+
# make sure that there is a node for each service
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative './node'
|
2
|
+
|
3
|
+
module Proctor
|
4
|
+
class Nodes
|
5
|
+
|
6
|
+
def initialize(app_files, params)
|
7
|
+
@app_files = app_files
|
8
|
+
@params = params
|
9
|
+
@all = node_list(app_files).map {|m| Node.new(*m)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def all
|
13
|
+
@all.sort {|a,b| a.name <=> b.name}
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by_name(name)
|
17
|
+
@all.find {|node| node.name == name}
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_handle(handle)
|
21
|
+
end
|
22
|
+
|
23
|
+
def names
|
24
|
+
@all.map {|node| node.name}.sort
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def node_data(app_files)
|
30
|
+
app_files.merged_data['nodes']
|
31
|
+
end
|
32
|
+
|
33
|
+
def node_list(app_files)
|
34
|
+
node_data(app_files).each_pair.map {|name,data| [name,data]}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Proctor
|
4
|
+
module Resource
|
5
|
+
module Erb
|
6
|
+
|
7
|
+
def render_group_template(manager, node, services, template, env)
|
8
|
+
header = generate_group_header(manager, node, template, env)
|
9
|
+
body = generate_group_erb(manager, node, services, template, env)
|
10
|
+
header + body
|
11
|
+
end
|
12
|
+
|
13
|
+
def render_service_template(manager, service, template, env)
|
14
|
+
header = generate_service_header(manager, service, template, env)
|
15
|
+
body = generate_service_erb(manager, service, template, env)
|
16
|
+
header + body
|
17
|
+
end
|
18
|
+
|
19
|
+
#private
|
20
|
+
|
21
|
+
def erb_ify_hash(hash, service, env)
|
22
|
+
hash.each_pair do |k,v|
|
23
|
+
case v
|
24
|
+
when String
|
25
|
+
begin
|
26
|
+
hash[k] = ERB.new(v).result(binding)
|
27
|
+
rescue
|
28
|
+
end
|
29
|
+
when Hash
|
30
|
+
hash[k] = erb_ify_hash(v, service, env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
hash
|
34
|
+
end
|
35
|
+
|
36
|
+
def erb_ify(manager_or_service, service, env)
|
37
|
+
manager_or_service.data.each_pair do |k,v|
|
38
|
+
case v
|
39
|
+
when String
|
40
|
+
manager_or_service.data[k] = ERB.new(v).result(binding)
|
41
|
+
when Hash
|
42
|
+
manager_or_service.data[k] = erb_ify_hash(v, service, env)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
manager_or_service
|
46
|
+
end
|
47
|
+
|
48
|
+
def erb_ify_services(services, env)
|
49
|
+
services.each_pair do |key,service|
|
50
|
+
service = erb_ify(service, service, env)
|
51
|
+
end
|
52
|
+
services
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate_group_header(_manager, node, template, env)
|
56
|
+
manager = erb_ify(_manager, node, env)
|
57
|
+
xfile = manager.data["node_filename"] || "#{node.name}.conf"
|
58
|
+
<<-EOF.gsub(' ','')
|
59
|
+
# Config file for #{manager.name}/#{node.name}
|
60
|
+
# Generated by Proctor #{Time.now.strftime("on %Y-%m-%d at %H:%M:%S")}
|
61
|
+
# Using template: #{template.name}
|
62
|
+
# Export path: #{manager.data["export_directory"]}/#{xfile}
|
63
|
+
# Start command: #{manager.data["start_command"]}
|
64
|
+
EOF
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_service_header(_manager, service, template, env)
|
68
|
+
manager = erb_ify(_manager, service, env)
|
69
|
+
xfile = manager.data["service_filename"] || "#{service.name}.conf"
|
70
|
+
<<-EOF.gsub(' ','')
|
71
|
+
# Config file for #{manager.name}/#{service.name}
|
72
|
+
# Generated by Proctor #{Time.now.strftime("on %Y-%m-%d at %H:%M:%S")}
|
73
|
+
# Using template: #{template.name}
|
74
|
+
# Export path: #{manager.data["export_directory"]}/#{xfile}
|
75
|
+
# Start command: #{manager.data["start_command"]}
|
76
|
+
EOF
|
77
|
+
end
|
78
|
+
|
79
|
+
def generate_group_erb(manager, node, services, template, env)
|
80
|
+
services = erb_ify_services(services, env)
|
81
|
+
erb = ERB.new(File.read(template.path),0,'-')
|
82
|
+
erb.result(binding)
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_service_erb(_manager, _service, template, env)
|
86
|
+
manager = erb_ify(_manager, _service, env)
|
87
|
+
service = erb_ify(_service, _service, env)
|
88
|
+
erb = ERB.new(File.read(template.path))
|
89
|
+
erb.result(binding)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Proctor
|
4
|
+
module Resource
|
5
|
+
module Lookup
|
6
|
+
|
7
|
+
def lookup_valid_manager(mgr_name, env)
|
8
|
+
names = env.managers.names
|
9
|
+
msg = "unrecognized manager (#{mgr_name}) use one of [#{names.join('|')}]"
|
10
|
+
unless names.include?(mgr_name)
|
11
|
+
raise UnrecognizedManagerName, msg
|
12
|
+
end
|
13
|
+
env.managers.find_by_name(mgr_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def lookup_valid_service(svc_name, env)
|
17
|
+
names = env.services.names
|
18
|
+
msg = "unrecognized service (#{svc_name}) use one of [#{names.join('|')}]"
|
19
|
+
unless names.include?(svc_name)
|
20
|
+
raise UnrecognizedServiceName, msg
|
21
|
+
end
|
22
|
+
env.services.find_by_name(svc_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def lookup_valid_node(node_name, env)
|
26
|
+
names = env.nodes.names
|
27
|
+
msg = "unrecognized node (#{node_name}) use one of [#{names.join('|')}]"
|
28
|
+
unless names.include?(node_name)
|
29
|
+
raise UnrecognizedNodeName, msg
|
30
|
+
end
|
31
|
+
env.nodes.find_by_name(node_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def lookup_valid_service_template(manager, service, env)
|
35
|
+
key1 = "#{manager}_#{service}_s"
|
36
|
+
key2 = "#{manager}_default_s"
|
37
|
+
names = env.template_files.names
|
38
|
+
tmpl_name = [key1, key2].find {|key| names.include?(key)}
|
39
|
+
if tmpl_name.nil?
|
40
|
+
msg = "service template not found for #{manager}/#{service}"
|
41
|
+
raise TemplateNotFound, msg
|
42
|
+
end
|
43
|
+
env.template_files.find_by_name(tmpl_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def lookup_valid_group_template(manager, node, env)
|
47
|
+
key1 = "#{manager}_#{node}_g"
|
48
|
+
key2 = "#{manager}_default_g"
|
49
|
+
names = env.template_files.names
|
50
|
+
tmpl_name = [key1, key2].find {|key| names.include?(key)}
|
51
|
+
if tmpl_name.nil?
|
52
|
+
msg = "group template not found for #{manager}/#{node}"
|
53
|
+
raise TemplateNotFound, msg
|
54
|
+
end
|
55
|
+
env.template_files.find_by_name(tmpl_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def lookup_valid_services(node_name, env)
|
59
|
+
node = lookup_valid_node(node_name, env)
|
60
|
+
node.services.map {|service| lookup_valid_service(service, env)}
|
61
|
+
end
|
62
|
+
|
63
|
+
def lookup_valid_services_hash(node_name, env)
|
64
|
+
lookup_valid_services(node_name, env).reduce({}) {|a,v| a[v.name]=v; a}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class UnrecognizedManagerName < RuntimeError
|
70
|
+
end
|
71
|
+
|
72
|
+
class UnrecognizedServiceName < RuntimeError
|
73
|
+
end
|
74
|
+
|
75
|
+
class UnrecognizedNodeName < RuntimeError
|
76
|
+
end
|
77
|
+
|
78
|
+
class TemplateNotFound < RuntimeError
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
data/lib/proctor/service.rb
CHANGED
@@ -1,8 +1,33 @@
|
|
1
|
+
require_relative './util/helpers'
|
2
|
+
|
1
3
|
module Proctor
|
4
|
+
|
2
5
|
class Service
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
+
|
7
|
+
include Proctor::Util::Helpers
|
8
|
+
|
9
|
+
attr_reader :name, :data, :handle
|
10
|
+
|
11
|
+
def initialize(name, data)
|
12
|
+
@name = name
|
13
|
+
@data = data
|
14
|
+
@handle = md5_handle(name)
|
15
|
+
#validate_required_service_fields(data)
|
6
16
|
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def validate_required_service_fields(service_hash)
|
21
|
+
required_fields = %w(start_command)
|
22
|
+
required_fields.each do |field|
|
23
|
+
if service_hash[field].nil?
|
24
|
+
raise MissingServiceField, "missing required service field (#{field})"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class MissingServiceField < RuntimeError
|
7
32
|
end
|
8
33
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative './service'
|
2
|
+
|
3
|
+
module Proctor
|
4
|
+
class Services
|
5
|
+
|
6
|
+
def initialize(app_files, params)
|
7
|
+
@app_files = app_files
|
8
|
+
@params = params
|
9
|
+
@all = service_list(app_files).map {|m| Service.new(*m)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def all
|
13
|
+
@all.sort {|a,b| a.name <=> b.name}
|
14
|
+
end
|
15
|
+
|
16
|
+
def names
|
17
|
+
@all.map {|s| s.name}.sort
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_name(name)
|
21
|
+
@all.find {|service| service.name == name}
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_by_handle(handle)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def service_data(app_files)
|
30
|
+
app_files.merged_data['services']
|
31
|
+
end
|
32
|
+
|
33
|
+
def service_list(app_files)
|
34
|
+
service_data(app_files).each_pair.map {|mgr_name,mgr_data| [mgr_name,mgr_data]}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/proctor.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path('../lib/proctor/version', __FILE__)
|
2
|
+
require File.expand_path('../lib/proctor/util/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
|
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.version = Proctor::VERSION
|
18
18
|
|
19
19
|
gem.add_dependency('gli')
|
20
|
+
gem.add_dependency('thor')
|
20
21
|
gem.add_dependency('foreman')
|
21
22
|
gem.add_dependency('hash-deep-merge')
|
22
23
|
|
data/proctor/Proctorfile
CHANGED
@@ -1,52 +1,53 @@
|
|
1
1
|
# vim: set ft=yaml:
|
2
2
|
---
|
3
|
-
|
4
3
|
managers:
|
5
|
-
init:
|
6
|
-
export_directory: "/etc/init.d"
|
7
4
|
upstart:
|
8
|
-
export_directory:
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
export_directory: "/etc/init"
|
6
|
+
group_data:
|
7
|
+
conf_filename: "tbd.conf"
|
8
|
+
start_command: "/sbin/init start <%= env.app['name'] %>"
|
9
|
+
pidfile: "pids/<%= env.app['name'] %>.pid"
|
10
|
+
logfile: "log/<%= env.app['name'] %>.log"
|
11
|
+
service_data:
|
12
|
+
conf_filename: "<%= service.name %>.conf"
|
13
|
+
start_command: "/sbin/init start <%= service.name %>"
|
14
|
+
stop_command: "/sbin/init stop <%= service.name %>"
|
15
|
+
status_command: "/sbin/init status <%= service.name %>"
|
12
16
|
monit:
|
13
17
|
export_directory: "/etc/monit/conf.d"
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
service_data:
|
19
|
+
reload_command: "monit reload"
|
20
|
+
stop_command: "monit quit"
|
21
|
+
start_command: "monit"
|
22
|
+
status_command: "monit summary"
|
23
|
+
pidfile: "/a/b/c"
|
19
24
|
foreman:
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
export_directory: "/tmp/proctor/foreman/<%= env.app['name'] %>"
|
26
|
+
group_data:
|
27
|
+
start_command: "cd /tmp/proctor/foreman/<%= env.app['name'] %> && foreman start"
|
28
|
+
conf_filename: "Procfile"
|
23
29
|
|
24
30
|
services:
|
25
31
|
unicorn:
|
26
|
-
start_command: "bin/unicorn --log_file shared/log/<%= name %>.log"
|
27
|
-
stop_command: "qwer"
|
32
|
+
start_command: "bin/unicorn --log_file shared/log/<%= env.app['name'] %>.log"
|
28
33
|
passenger:
|
29
|
-
start_command: "bin/passenger --log_file shared/log/<%= name %>.log"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
exports_to: ['monit', 'upstart']
|
35
|
-
start_command: "script/faye_script.sh"
|
36
|
-
port: 2343
|
34
|
+
start_command: "bin/passenger --log_file shared/log/<%= env.app['name'] %>.log"
|
35
|
+
showtime:
|
36
|
+
start_command: "<%= env.app['gemdir'] %>/bin/showtime"
|
37
|
+
showlog:
|
38
|
+
start_command: "<%= env.app['gemdir'] %>/bin/showlog"
|
37
39
|
|
38
40
|
nodes:
|
39
|
-
|
41
|
+
development:
|
42
|
+
- passenger
|
43
|
+
test:
|
44
|
+
- showtime
|
45
|
+
- showlog
|
46
|
+
staging:
|
40
47
|
- passenger
|
41
|
-
- faye
|
42
|
-
- postgres-standalone
|
43
|
-
- jobq
|
44
|
-
- renderpro
|
45
|
-
- redis
|
46
48
|
production:
|
47
49
|
- unicorn
|
48
|
-
-
|
49
|
-
- postgres-shared
|
50
|
+
- passenger
|
50
51
|
backup:
|
51
|
-
-
|
52
|
+
- showtime
|
52
53
|
|