proctor 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/.rspec +1 -0
  2. data/TODO +28 -0
  3. data/bin/proctor +55 -85
  4. data/bin/showlog +5 -0
  5. data/bin/showtime +5 -0
  6. data/lib/proctor/command/asset_list_cmd.rb +56 -0
  7. data/lib/proctor/{presenter/show.rb → command/asset_show_cmd.rb} +7 -2
  8. data/lib/proctor/command/file_cleanup_cmd.rb +81 -0
  9. data/lib/proctor/command/file_export_cmd.rb +79 -0
  10. data/lib/proctor/command/helpers/command.rb +27 -0
  11. data/lib/proctor/command/render_group_cmd.rb +39 -0
  12. data/lib/proctor/command/render_service_cmd.rb +34 -0
  13. data/lib/proctor/command/start_cmd.rb +70 -0
  14. data/lib/proctor/config/app_file.rb +54 -0
  15. data/lib/proctor/config/app_files.rb +50 -0
  16. data/lib/proctor/config/env.rb +35 -0
  17. data/lib/proctor/config/template_file.rb +41 -0
  18. data/lib/proctor/config/template_files.rb +39 -0
  19. data/lib/proctor/manager.rb +36 -3
  20. data/lib/proctor/managers.rb +38 -0
  21. data/lib/proctor/node.rb +26 -0
  22. data/lib/proctor/nodes.rb +38 -0
  23. data/lib/proctor/resource/erb.rb +95 -0
  24. data/lib/proctor/resource/lookup.rb +82 -0
  25. data/lib/proctor/service.rb +28 -3
  26. data/lib/proctor/services.rb +38 -0
  27. data/lib/proctor/util/helpers.rb +13 -0
  28. data/lib/proctor/util/version.rb +3 -0
  29. data/proctor.gemspec +2 -1
  30. data/proctor/Proctorfile +35 -34
  31. data/proctor/templates/foreman_default_g.erb +3 -0
  32. data/proctor/templates/monit_default_s.erb +3 -6
  33. data/proctor/templates/monit_faye_s.erb +3 -3
  34. data/proctor/templates/upstart_default_g.erb +1 -0
  35. data/proctor/templates/upstart_default_s.erb +1 -3
  36. data/proctor/templates/upstart_passenger_s.erb +3 -0
  37. data/spec/acceptance/asset_list_spec.rb +16 -0
  38. data/spec/acceptance/asset_show_spec.rb +16 -0
  39. data/spec/acceptance/file_cleanup_spec.rb +16 -0
  40. data/spec/acceptance/file_export_spec.rb +16 -0
  41. data/spec/acceptance/render_group_spec.rb +15 -0
  42. data/spec/acceptance/render_service_spec.rb +16 -0
  43. data/spec/acceptance/start_spec.rb +16 -0
  44. data/spec/spec_helper.rb +22 -0
  45. data/spec/unit/command/file_export_cmd_spec.rb +46 -0
  46. data/spec/unit/command/file_list_cmd_spec.rb +30 -0
  47. data/spec/unit/command/render_group_cmd_spec.rb +44 -0
  48. data/spec/unit/command/render_service_cmd_spec.rb +42 -0
  49. data/spec/unit/{app_file_spec.rb → config/app_file_spec.rb} +27 -7
  50. data/spec/unit/config/app_files_spec.rb +55 -0
  51. data/spec/unit/config/env_spec.rb +37 -0
  52. data/spec/unit/config/template_file_spec.rb +55 -0
  53. data/spec/unit/config/template_files_spec.rb +32 -0
  54. data/spec/unit/manager_spec.rb +30 -10
  55. data/spec/unit/managers_spec.rb +40 -0
  56. data/spec/unit/node_spec.rb +34 -0
  57. data/spec/unit/nodes_spec.rb +36 -0
  58. data/spec/unit/service_spec.rb +31 -10
  59. data/spec/unit/services_spec.rb +34 -0
  60. metadata +86 -31
  61. data/Proctorfile +0 -4
  62. data/lib/proctor/app_config.rb +0 -23
  63. data/lib/proctor/app_file.rb +0 -44
  64. data/lib/proctor/cmd_state.rb +0 -39
  65. data/lib/proctor/presenter/list.rb +0 -67
  66. data/lib/proctor/presenter/render.rb +0 -39
  67. data/lib/proctor/template.rb +0 -5
  68. data/lib/proctor/template_config.rb +0 -22
  69. data/lib/proctor/template_file.rb +0 -44
  70. data/lib/proctor/util.rb +0 -12
  71. data/lib/proctor/version.rb +0 -3
  72. data/proctor/templates/foreman_default_n.erb +0 -9
  73. data/proctor/templates/monit_web_s.erb +0 -0
  74. data/proctor/templates/upstart_default_n.erb +0 -0
  75. data/spec/acceptance/help_spec.rb +0 -36
  76. data/spec/acceptance/list_spec.rb +0 -17
  77. data/spec/unit/app_config_spec.rb +0 -30
  78. data/spec/unit/template_config_spec.rb +0 -12
  79. data/spec/unit/template_file_spec.rb +0 -16
  80. 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
@@ -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
@@ -1,8 +1,33 @@
1
+ require_relative './util/helpers'
2
+
1
3
  module Proctor
4
+
2
5
  class Service
3
- attr_reader :input_hash, :opts
4
- def initialize(hash = {})
5
- @input_hash = hash
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
@@ -0,0 +1,13 @@
1
+ require 'digest/md5'
2
+
3
+ module Proctor
4
+ module Util
5
+ module Helpers
6
+
7
+ def md5_handle(string)
8
+ Digest::MD5.hexdigest(string)[0..2]
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Proctor
2
+ VERSION = "0.0.4"
3
+ 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: "/etc/init"
9
- start_command: "/sbin/init start <%= app_name %>"
10
- stop_command: "/sbin/init stop <%= app_name %>"
11
- status_command: "/sbin/init status <%= app_name %>"
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
- reload_command: "monit reload"
15
- stop_command: "monit quit"
16
- start_command: "monit"
17
- status_command: "monit summary"
18
- pidfile: "/a/b/c"
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
- start_command: "foreman start"
21
- use_master_template: true
22
- use_worker_template: false
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
- stop_command: "qwer"
31
- faye:
32
- start_command: "qwer"
33
- export.monit.memory_limit: "<%= ForemanEnv.production? ? '20MB' : '10MB' %>"
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
- dev:
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
- - faye
49
- - postgres-shared
50
+ - passenger
50
51
  backup:
51
- - postgres
52
+ - showtime
52
53