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.
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