meepo 1.5.2

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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +16 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +29 -0
  6. data/.travis.yml +10 -0
  7. data/Dockerfile +7 -0
  8. data/Gemfile +13 -0
  9. data/MIT-LICENSE +20 -0
  10. data/Rakefile +15 -0
  11. data/TODO +5 -0
  12. data/bin/invoker +7 -0
  13. data/contrib/completion/invoker-completion.bash +70 -0
  14. data/contrib/completion/invoker-completion.zsh +62 -0
  15. data/examples/hello_sinatra.rb +26 -0
  16. data/examples/sample.ini +3 -0
  17. data/invoker.gemspec +43 -0
  18. data/lib/invoker.rb +152 -0
  19. data/lib/invoker/cli.rb +159 -0
  20. data/lib/invoker/cli/pinger.rb +23 -0
  21. data/lib/invoker/cli/question.rb +15 -0
  22. data/lib/invoker/cli/tail.rb +34 -0
  23. data/lib/invoker/cli/tail_watcher.rb +34 -0
  24. data/lib/invoker/command_worker.rb +60 -0
  25. data/lib/invoker/commander.rb +95 -0
  26. data/lib/invoker/daemon.rb +126 -0
  27. data/lib/invoker/dns_cache.rb +23 -0
  28. data/lib/invoker/errors.rb +17 -0
  29. data/lib/invoker/event/manager.rb +79 -0
  30. data/lib/invoker/ipc.rb +45 -0
  31. data/lib/invoker/ipc/add_command.rb +12 -0
  32. data/lib/invoker/ipc/add_http_command.rb +10 -0
  33. data/lib/invoker/ipc/base_command.rb +24 -0
  34. data/lib/invoker/ipc/client_handler.rb +26 -0
  35. data/lib/invoker/ipc/dns_check_command.rb +17 -0
  36. data/lib/invoker/ipc/list_command.rb +11 -0
  37. data/lib/invoker/ipc/message.rb +170 -0
  38. data/lib/invoker/ipc/message/list_response.rb +35 -0
  39. data/lib/invoker/ipc/message/tail_response.rb +10 -0
  40. data/lib/invoker/ipc/ping_command.rb +10 -0
  41. data/lib/invoker/ipc/reload_command.rb +12 -0
  42. data/lib/invoker/ipc/remove_command.rb +12 -0
  43. data/lib/invoker/ipc/server.rb +26 -0
  44. data/lib/invoker/ipc/tail_command.rb +11 -0
  45. data/lib/invoker/ipc/unix_client.rb +60 -0
  46. data/lib/invoker/logger.rb +13 -0
  47. data/lib/invoker/parsers/config.rb +184 -0
  48. data/lib/invoker/parsers/procfile.rb +86 -0
  49. data/lib/invoker/power/balancer.rb +131 -0
  50. data/lib/invoker/power/config.rb +77 -0
  51. data/lib/invoker/power/dns.rb +38 -0
  52. data/lib/invoker/power/http_parser.rb +68 -0
  53. data/lib/invoker/power/http_response.rb +81 -0
  54. data/lib/invoker/power/pf_migrate.rb +64 -0
  55. data/lib/invoker/power/port_finder.rb +49 -0
  56. data/lib/invoker/power/power.rb +3 -0
  57. data/lib/invoker/power/powerup.rb +29 -0
  58. data/lib/invoker/power/setup.rb +90 -0
  59. data/lib/invoker/power/setup/distro/arch.rb +15 -0
  60. data/lib/invoker/power/setup/distro/base.rb +57 -0
  61. data/lib/invoker/power/setup/distro/debian.rb +11 -0
  62. data/lib/invoker/power/setup/distro/mint.rb +10 -0
  63. data/lib/invoker/power/setup/distro/opensuse.rb +11 -0
  64. data/lib/invoker/power/setup/distro/redhat.rb +11 -0
  65. data/lib/invoker/power/setup/distro/ubuntu.rb +10 -0
  66. data/lib/invoker/power/setup/files/invoker_forwarder.sh.erb +17 -0
  67. data/lib/invoker/power/setup/files/socat_invoker.service +12 -0
  68. data/lib/invoker/power/setup/linux_setup.rb +105 -0
  69. data/lib/invoker/power/setup/osx_setup.rb +137 -0
  70. data/lib/invoker/power/templates/400.html +40 -0
  71. data/lib/invoker/power/templates/404.html +40 -0
  72. data/lib/invoker/power/templates/503.html +40 -0
  73. data/lib/invoker/power/url_rewriter.rb +40 -0
  74. data/lib/invoker/process_manager.rb +198 -0
  75. data/lib/invoker/process_printer.rb +43 -0
  76. data/lib/invoker/reactor.rb +37 -0
  77. data/lib/invoker/reactor/reader.rb +54 -0
  78. data/lib/invoker/version.rb +47 -0
  79. data/readme.md +25 -0
  80. data/spec/invoker/cli/pinger_spec.rb +22 -0
  81. data/spec/invoker/cli/tail_watcher_spec.rb +39 -0
  82. data/spec/invoker/cli_spec.rb +27 -0
  83. data/spec/invoker/command_worker_spec.rb +45 -0
  84. data/spec/invoker/commander_spec.rb +152 -0
  85. data/spec/invoker/config_spec.rb +361 -0
  86. data/spec/invoker/daemon_spec.rb +34 -0
  87. data/spec/invoker/event/manager_spec.rb +67 -0
  88. data/spec/invoker/invoker_spec.rb +71 -0
  89. data/spec/invoker/ipc/client_handler_spec.rb +54 -0
  90. data/spec/invoker/ipc/dns_check_command_spec.rb +32 -0
  91. data/spec/invoker/ipc/message/list_response_spec.rb +24 -0
  92. data/spec/invoker/ipc/message_spec.rb +49 -0
  93. data/spec/invoker/ipc/unix_client_spec.rb +29 -0
  94. data/spec/invoker/power/balancer_spec.rb +22 -0
  95. data/spec/invoker/power/config_spec.rb +18 -0
  96. data/spec/invoker/power/http_parser_spec.rb +32 -0
  97. data/spec/invoker/power/http_response_spec.rb +34 -0
  98. data/spec/invoker/power/pf_migrate_spec.rb +87 -0
  99. data/spec/invoker/power/port_finder_spec.rb +16 -0
  100. data/spec/invoker/power/setup/linux_setup_spec.rb +103 -0
  101. data/spec/invoker/power/setup/osx_setup_spec.rb +105 -0
  102. data/spec/invoker/power/setup_spec.rb +4 -0
  103. data/spec/invoker/power/url_rewriter_spec.rb +70 -0
  104. data/spec/invoker/power/web_sockets_spec.rb +61 -0
  105. data/spec/invoker/process_manager_spec.rb +130 -0
  106. data/spec/invoker/reactor_spec.rb +6 -0
  107. data/spec/spec_helper.rb +43 -0
  108. metadata +389 -0
@@ -0,0 +1,49 @@
1
+ module Invoker
2
+ module Power
3
+ class PortFinder
4
+ STARTING_PORT = 23400
5
+ attr_accessor :dns_port, :http_port, :starting_port, :https_port
6
+ def initialize
7
+ @starting_port = STARTING_PORT
8
+ @ports = []
9
+ @dns_port = nil
10
+ @http_port = nil
11
+ end
12
+
13
+ def find_ports
14
+ STARTING_PORT.upto(STARTING_PORT + 100) do |port|
15
+ break if @ports.size > 3
16
+ if check_if_port_is_open(port)
17
+ @ports << port
18
+ else
19
+ next
20
+ end
21
+ end
22
+ @dns_port = @ports[0]
23
+ @http_port = @ports[1]
24
+ @https_port = @ports[2]
25
+ end
26
+
27
+ private
28
+
29
+ def check_if_port_is_open(port)
30
+ socket_flag = true
31
+ sockets = nil
32
+ begin
33
+ sockets = Socket.tcp_server_sockets(port)
34
+ socket_flag = false if sockets.size <= 1
35
+ rescue Errno::EADDRINUSE
36
+ socket_flag = false
37
+ end
38
+ sockets && close_socket_pairs(sockets)
39
+ socket_flag
40
+ end
41
+
42
+ def close_socket_pairs(sockets)
43
+ sockets.each { |s| s.close }
44
+ rescue
45
+ nil
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ require "invoker/power/http_response"
2
+ require "invoker/power/dns"
3
+ require "invoker/power/balancer"
@@ -0,0 +1,29 @@
1
+ module Invoker
2
+ # power is really a stupid pun on pow.
3
+ module Power
4
+ class Powerup
5
+ def self.fork_and_start
6
+ powerup = new()
7
+ fork { powerup.run }
8
+ end
9
+
10
+ def run
11
+ require "invoker/power/power"
12
+ EM.epoll
13
+ EM.run {
14
+ trap("TERM") { stop }
15
+ trap("INT") { stop }
16
+ if Invoker.darwin?
17
+ DNS.new.run(listen: DNS.server_ports)
18
+ end
19
+ Balancer.run
20
+ }
21
+ end
22
+
23
+ def stop
24
+ Invoker::Logger.puts "Terminating Proxy/Server"
25
+ EventMachine.stop
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,90 @@
1
+ require "eventmachine"
2
+
3
+ module Invoker
4
+ module Power
5
+ class Setup
6
+ attr_accessor :port_finder, :tld
7
+
8
+ def self.install(tld)
9
+ selected_installer_klass = installer_klass
10
+ selected_installer_klass.new(tld).install
11
+ end
12
+
13
+ def self.uninstall
14
+ power_config = Invoker::Power::Config.load_config
15
+ selected_installer_klass = installer_klass
16
+ selected_installer_klass.new(power_config.tld).uninstall_invoker
17
+ end
18
+
19
+ def self.installer_klass
20
+ if Invoker.darwin?
21
+ Invoker::Power::OsxSetup
22
+ else
23
+ Invoker::Power::LinuxSetup
24
+ end
25
+ end
26
+
27
+ def initialize(tld)
28
+ if tld !~ /^[a-z]+$/
29
+ Invoker::Logger.puts("Please specify valid tld".color(:red))
30
+ exit(1)
31
+ end
32
+ self.tld = tld
33
+ end
34
+
35
+ def install
36
+ if check_if_setup_can_run?
37
+ setup_invoker
38
+ else
39
+ Invoker::Logger.puts("The setup has been already run.".color(:red))
40
+ end
41
+ self
42
+ end
43
+
44
+ def drop_to_normal_user
45
+ EventMachine.set_effective_user(ENV["SUDO_USER"])
46
+ end
47
+
48
+ def find_open_ports
49
+ port_finder.find_ports()
50
+ end
51
+
52
+ def port_finder
53
+ @port_finder ||= Invoker::Power::PortFinder.new()
54
+ end
55
+
56
+ def check_if_setup_can_run?
57
+ !File.exists?(Invoker::Power::Config.config_file)
58
+ end
59
+
60
+ def create_config_file
61
+ Invoker.setup_config_location
62
+ config = build_power_config
63
+ Invoker::Power::Config.create(config)
64
+ end
65
+
66
+ # Builds and returns power config hash. Override this method in subclasses if necessary.
67
+ def build_power_config
68
+ config = {
69
+ http_port: port_finder.http_port,
70
+ https_port: port_finder.https_port,
71
+ tld: tld
72
+ }
73
+ config
74
+ end
75
+
76
+ def remove_resolver_file
77
+ begin
78
+ safe_remove_file(resolver_file)
79
+ rescue Errno::EACCES
80
+ Invoker::Logger.puts("Running uninstall requires root access, please rerun it with sudo".color(:red))
81
+ raise
82
+ end
83
+ end
84
+
85
+ def safe_remove_file(file)
86
+ File.delete(file) if File.exists?(file)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,15 @@
1
+ module Invoker
2
+ module Power
3
+ module Distro
4
+ class Arch < Base
5
+ def install_required_software
6
+ system("pacman -S --needed --noconfirm dnsmasq socat")
7
+ system("mkdir -p /etc/dnsmasq.d")
8
+ unless File.open("/etc/dnsmasq.conf").each_line.any? { |line| line.chomp == "conf-dir=/etc/dnsmasq.d" }
9
+ File.open("/etc/dnsmasq.conf", "a") {|f| f.write("conf-dir=/etc/dnsmasq.d") }
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ module Invoker
2
+ module Power
3
+ module Distro
4
+ class Base
5
+ SOCAT_SHELLSCRIPT = "/usr/bin/invoker_forwarder.sh"
6
+ SOCAT_SYSTEMD = "/etc/systemd/system/socat_invoker.service"
7
+ RESOLVER_DIR = "/etc/dnsmasq.d"
8
+ attr_accessor :tld
9
+
10
+ def resolver_file
11
+ File.join(RESOLVER_DIR, "#{tld}-tld")
12
+ end
13
+
14
+ def self.distro_installer(tld)
15
+ case Facter[:operatingsystem].value
16
+ when "Ubuntu"
17
+ require "invoker/power/setup/distro/ubuntu"
18
+ Ubuntu.new(tld)
19
+ when "Fedora"
20
+ require "invoker/power/setup/distro/redhat"
21
+ Redhat.new(tld)
22
+ when "Archlinux"
23
+ require "invoker/power/setup/distro/arch"
24
+ Arch.new(tld)
25
+ when "Debian"
26
+ require "invoker/power/setup/distro/debian"
27
+ Debian.new(tld)
28
+ when "LinuxMint"
29
+ require "invoker/power/setup/distro/mint"
30
+ Mint.new(tld)
31
+ when "OpenSuSE"
32
+ require "invoker/power/setup/distro/opensuse"
33
+ Opensuse.new(tld)
34
+ else
35
+ raise "Your selected distro is not supported by Invoker"
36
+ end
37
+ end
38
+
39
+ def initialize(tld)
40
+ self.tld = tld
41
+ end
42
+
43
+ # Install required software
44
+ def install_required_software
45
+ raise "Unimplemented"
46
+ end
47
+
48
+ def restart_services
49
+ system("systemctl enable socat_invoker.service")
50
+ system("systemctl enable dnsmasq")
51
+ system("systemctl start socat_invoker.service")
52
+ system("systemctl restart dnsmasq")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ module Invoker
2
+ module Power
3
+ module Distro
4
+ class Debian < Base
5
+ def install_required_software
6
+ system("apt-get --assume-yes install dnsmasq socat")
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require "invoker/power/setup/distro/ubuntu"
2
+
3
+ module Invoker
4
+ module Power
5
+ module Distro
6
+ class Mint < Ubuntu
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Invoker
2
+ module Power
3
+ module Distro
4
+ class Opensuse < Base
5
+ def install_required_software
6
+ system("zypper install -l dnsmasq socat")
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Invoker
2
+ module Power
3
+ module Distro
4
+ class Redhat < Base
5
+ def install_required_software
6
+ system("yum --assumeyes install dnsmasq socat")
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require "invoker/power/setup/distro/debian"
2
+
3
+ module Invoker
4
+ module Power
5
+ module Distro
6
+ class Ubuntu < Debian
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ set -e
3
+ KillJobs() {
4
+ for job in $(jobs -p); do
5
+ kill -s SIGTERM $job > /dev/null 2>&1 || (sleep 10 && kill -9 $job > /dev/null 2>&1 &)
6
+ done
7
+ }
8
+
9
+ # Whatever you need to clean here
10
+ trap KillJobs SIGINT SIGTERM EXIT
11
+
12
+ /usr/bin/socat TCP-LISTEN:80,reuseaddr,fork TCP:0.0.0.0:<%= http_port %>&
13
+ pid1=$!
14
+ /usr/bin/socat TCP-LISTEN:443,reuseaddr,fork TCP:0.0.0.0:<%= https_port %>&
15
+ pid2=$!
16
+ wait $pid1 $pid2
17
+ wait $pid1 $pid2
@@ -0,0 +1,12 @@
1
+ [Unit]
2
+ Description=Socat port forwarding service
3
+ After=network.target
4
+ Documentation=man:socat(1)
5
+
6
+ [Service]
7
+ ExecStart=/usr/bin/invoker_forwarder.sh
8
+ Restart=on-success
9
+
10
+
11
+ [Install]
12
+ WantedBy=multi-user.target
@@ -0,0 +1,105 @@
1
+ require "invoker/power/setup/distro/base"
2
+ require "facter"
3
+ require 'erb'
4
+ require 'fileutils'
5
+
6
+ module Invoker
7
+ module Power
8
+ class LinuxSetup < Setup
9
+ attr_accessor :distro_installer
10
+
11
+ def setup_invoker
12
+ if get_user_confirmation?
13
+ initialize_distro_installer
14
+ find_open_ports
15
+ distro_installer.install_required_software
16
+ install_resolver
17
+ install_port_forwarder
18
+ distro_installer.restart_services
19
+ drop_to_normal_user
20
+ create_config_file
21
+ else
22
+ Invoker::Logger.puts("Invoker is not configured to serve from subdomains".color(:red))
23
+ end
24
+ self
25
+ end
26
+
27
+ def uninstall_invoker
28
+ system("systemctl disable socat_invoker.service")
29
+ system("systemctl stop socat_invoker.service")
30
+ system("rm #{Invoker::Power::Distro::Base::SOCAT_SYSTEMD}")
31
+ system("rm #{Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT}")
32
+ initialize_distro_installer
33
+ remove_resolver_file
34
+ drop_to_normal_user
35
+ Invoker::Power::Config.delete
36
+ end
37
+
38
+ def resolver_file
39
+ distro_installer.resolver_file
40
+ end
41
+
42
+ def forwarder_script
43
+ File.join(File.dirname(__FILE__), "files/invoker_forwarder.sh.erb")
44
+ end
45
+
46
+ def socat_unit
47
+ File.join(File.dirname(__FILE__), "files/socat_invoker.service")
48
+ end
49
+
50
+ private
51
+
52
+ def initialize_distro_installer
53
+ # Create a new facter check for systemctl (in systemd)
54
+ Facter.add(:systemctl) do
55
+ setcode do
56
+ Facter::Util::Resolution.exec("[ -e /usr/bin/systemctl ] && echo 'true' || echo 'false'")
57
+ end
58
+ end
59
+ @distro_installer = Invoker::Power::Distro::Base.distro_installer(tld)
60
+ end
61
+
62
+ def install_resolver
63
+ File.open(resolver_file, "w") do |fl|
64
+ fl.write(resolver_file_content)
65
+ end
66
+ end
67
+
68
+ def install_port_forwarder
69
+ install_forwarder_script(port_finder.http_port, port_finder.https_port)
70
+ install_systemd_unit
71
+ end
72
+
73
+ def resolver_file_content
74
+ content =<<-EOD
75
+ local=/#{tld}/
76
+ address=/#{tld}/127.0.0.1
77
+ EOD
78
+ content
79
+ end
80
+
81
+ def install_forwarder_script(http_port, https_port)
82
+ script_template = File.read(forwarder_script)
83
+ renderer = ERB.new(script_template)
84
+ script_output = renderer.result(binding)
85
+ File.open(Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT, "w") do |fl|
86
+ fl.write(script_output)
87
+ end
88
+ system("chmod +x #{Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT}")
89
+ end
90
+
91
+ def install_systemd_unit
92
+ FileUtils.cp(socat_unit, Invoker::Power::Distro::Base::SOCAT_SYSTEMD)
93
+ system("chmod 644 #{Invoker::Power::Distro::Base::SOCAT_SYSTEMD}")
94
+ end
95
+
96
+ def get_user_confirmation?
97
+ Invoker::Logger.puts("Invoker is going to install dnsmasq and socat on this machine."\
98
+ " It is also going to install a local resolver for .#{tld} domain and a socat service"\
99
+ " which will forward all local requests on port 80 and 443 to another port")
100
+ Invoker::Logger.puts("If you still want to proceed with installation, press y.")
101
+ Invoker::CLI::Question.agree("Proceed with installation (y/n) : ")
102
+ end
103
+ end
104
+ end
105
+ end