proctor 0.0.3 → 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.
- 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
|
|