rails-service 0.1.0

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 (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +99 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +21 -0
  8. data/README.md +71 -0
  9. data/Rakefile +16 -0
  10. data/app/controller/rails/service/admin_controller.rb +32 -0
  11. data/app/controller/rails/service/base_controller.rb +3 -0
  12. data/app/controller/rails/service/status_controller.rb +44 -0
  13. data/app/helpers/rails/service/admin_helper.rb +27 -0
  14. data/app/views/layouts/admin.html +100 -0
  15. data/app/views/rails/service/admin/config.html.erb +3 -0
  16. data/app/views/rails/service/admin/environment.html.erb +16 -0
  17. data/app/views/rails/service/admin/manifest.html.erb +1 -0
  18. data/app/views/rails/service/admin/rails_properties.html.erb +1 -0
  19. data/app/views/rails/service/admin/routing.html.erb +1 -0
  20. data/bin/console +8 -0
  21. data/bin/setup +7 -0
  22. data/config/routes.rb +9 -0
  23. data/lib/rails/service.rb +29 -0
  24. data/lib/rails/service/admin_view_resolver.rb +18 -0
  25. data/lib/rails/service/app_config.rb +28 -0
  26. data/lib/rails/service/boot.rb +23 -0
  27. data/lib/rails/service/config.rb +128 -0
  28. data/lib/rails/service/context.rb +13 -0
  29. data/lib/rails/service/core_ext/deep_struct.rb +23 -0
  30. data/lib/rails/service/engine.rb +20 -0
  31. data/lib/rails/service/manifest.rb +27 -0
  32. data/lib/rails/service/version.rb +5 -0
  33. data/rails-service.gemspec +22 -0
  34. data/spec/controllers/admin_controller_spec.rb +51 -0
  35. data/spec/controllers/status_controller_spec.rb +21 -0
  36. data/spec/fixtures/app-manifest.yaml +7 -0
  37. data/spec/lib/app_config_spec.rb +35 -0
  38. data/spec/lib/context_spec.rb +22 -0
  39. data/spec/lib/manifest_spec.rb +62 -0
  40. data/spec/rails_app/README.rdoc +28 -0
  41. data/spec/rails_app/Rakefile +6 -0
  42. data/spec/rails_app/app-manifest.yaml +6 -0
  43. data/spec/rails_app/app/assets/images/.keep +0 -0
  44. data/spec/rails_app/app/assets/javascripts/application.js +13 -0
  45. data/spec/rails_app/app/assets/stylesheets/application.css +15 -0
  46. data/spec/rails_app/app/controllers/application_controller.rb +5 -0
  47. data/spec/rails_app/app/controllers/concerns/.keep +0 -0
  48. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  49. data/spec/rails_app/app/mailers/.keep +0 -0
  50. data/spec/rails_app/app/models/.keep +0 -0
  51. data/spec/rails_app/app/models/concerns/.keep +0 -0
  52. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  53. data/spec/rails_app/bin/bundle +3 -0
  54. data/spec/rails_app/bin/rails +4 -0
  55. data/spec/rails_app/bin/rake +4 -0
  56. data/spec/rails_app/bin/setup +29 -0
  57. data/spec/rails_app/config.ru +4 -0
  58. data/spec/rails_app/config/app-config.yaml +8 -0
  59. data/spec/rails_app/config/application.rb +17 -0
  60. data/spec/rails_app/config/boot.rb +5 -0
  61. data/spec/rails_app/config/database.yml +25 -0
  62. data/spec/rails_app/config/environment.rb +5 -0
  63. data/spec/rails_app/config/environments/development.rb +41 -0
  64. data/spec/rails_app/config/environments/production.rb +79 -0
  65. data/spec/rails_app/config/environments/test.rb +42 -0
  66. data/spec/rails_app/config/initializers/assets.rb +11 -0
  67. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  68. data/spec/rails_app/config/initializers/cookies_serializer.rb +3 -0
  69. data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/spec/rails_app/config/initializers/inflections.rb +16 -0
  71. data/spec/rails_app/config/initializers/mime_types.rb +4 -0
  72. data/spec/rails_app/config/initializers/session_store.rb +3 -0
  73. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  74. data/spec/rails_app/config/locales/en.yml +23 -0
  75. data/spec/rails_app/config/routes.rb +4 -0
  76. data/spec/rails_app/config/secrets.yml +22 -0
  77. data/spec/rails_app/db/test.sqlite3 +0 -0
  78. data/spec/rails_app/lib/assets/.keep +0 -0
  79. data/spec/rails_app/lib/custom_admin_actions.rb +7 -0
  80. data/spec/rails_app/lib/service/admin/actions.rb +11 -0
  81. data/spec/rails_app/lib/service/admin/views/foobar.html.erb +1 -0
  82. data/spec/rails_app/lib/service/status/actions.rb +11 -0
  83. data/spec/rails_app/log/.keep +0 -0
  84. data/spec/rails_app/public/404.html +67 -0
  85. data/spec/rails_app/public/422.html +67 -0
  86. data/spec/rails_app/public/500.html +66 -0
  87. data/spec/rails_app/public/favicon.ico +0 -0
  88. data/spec/routes_spec.rb +32 -0
  89. data/spec/spec_helper.rb +16 -0
  90. metadata +208 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2110edea5108743293e9c6e159508122699f94c5
4
+ data.tar.gz: 2b018c9fe11832e3b44388f15f734db36f6fe5b4
5
+ SHA512:
6
+ metadata.gz: 1a22e7839a01fd32021f6a3d6d15e6f447bf9413330ba67abbeae61084b95d3a75caf64ea7718a368c1edfd3168454fc5fd8bc4f86051a61317dbbea18da81b7
7
+ data.tar.gz: b5f1931efc7f5118bc4021b49377701d7389564fbf6cfaf8d4839a4ccd06c7c4d1e633dc249beca4354b0010a590924eeadeb0676954a7d1180943cdb9b63a52
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format progress
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,99 @@
1
+ AllCops:
2
+ RunRailsCops: true
3
+ Exclude:
4
+ - 'bin/**/*'
5
+ - '*.gemspec'
6
+
7
+ Lint/EndAlignment:
8
+ AlignWith: variable
9
+
10
+ Lint/Loop:
11
+ Enabled: false
12
+
13
+ Metrics/BlockNesting:
14
+ Max: 4
15
+
16
+ Metrics/ClassLength:
17
+ Max: 1045
18
+
19
+ Metrics/MethodLength:
20
+ Max: 418
21
+
22
+ # We'd like to get this down to 120. But we have to start somewhere.
23
+ Metrics/LineLength:
24
+ Max: 300
25
+
26
+ Metrics/AbcSize:
27
+ Max: 40
28
+
29
+ Metrics/CyclomaticComplexity:
30
+ Max: 10
31
+
32
+ Metrics/PerceivedComplexity:
33
+ Max: 10
34
+
35
+ Rails/ActionFilter:
36
+ EnforcedStyle: filter
37
+
38
+ Style/CaseIndentation:
39
+ IndentWhenRelativeTo: end
40
+
41
+ Style/CollectionMethods:
42
+ PreferredMethods:
43
+ find: detect
44
+
45
+ Style/DotPosition:
46
+ EnforcedStyle: trailing
47
+
48
+ Style/EmptyLineBetweenDefs:
49
+ AllowAdjacentOneLineDefs: true
50
+
51
+ Style/Encoding:
52
+ EnforcedStyle: when_needed
53
+
54
+ Style/HashSyntax:
55
+ EnforcedStyle: ruby19
56
+
57
+ Style/IndentHash:
58
+ EnforcedStyle: consistent
59
+
60
+ Style/MultilineOperationIndentation:
61
+ EnforcedStyle: indented
62
+
63
+ Style/Semicolon:
64
+ AllowAsExpressionSeparator: true
65
+
66
+ Style/TrailingComma:
67
+ EnforcedStyleForMultiline: comma
68
+
69
+ Style/TrivialAccessors:
70
+ AllowDSLWriters: true
71
+ AllowPredicates: true
72
+ ExactNameMatch: true
73
+
74
+ Documentation:
75
+ Enabled: false
76
+
77
+ Style/SignalException:
78
+ EnforcedStyle: only_raise
79
+
80
+ Style/AlignParameters:
81
+ EnforcedStyle: with_fixed_indentation
82
+
83
+ Style/MultilineOperationIndentation:
84
+ EnforcedStyle: indented
85
+
86
+ Style/FirstParameterIndentation:
87
+ EnforcedStyle: consistent
88
+
89
+ Style/TrailingUnderscoreVariable:
90
+ Enabled: false
91
+
92
+ Style/ParallelAssignment:
93
+ Enabled: false
94
+
95
+ Metrics/ModuleLength:
96
+ Enabled: false
97
+
98
+ Style/AccessorMethodName:
99
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ before_install: gem install bundler -v 1.10.3
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'pry'
6
+
7
+ group :test do
8
+ gem 'rspec'
9
+ gem 'rspec-rails'
10
+ gem 'sqlite3'
11
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Łukasz Strzałkowski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Microservices on Rails
2
+
3
+ Rails::Service is an opinioned Rails Engine providing boiler plate needed for
4
+ making microservice Rails application.
5
+
6
+ ## Note on Microservices
7
+
8
+ Microservices architecture is a great way to build and scale huge distributed
9
+ applications. It implies though that it's not for everybody and you're probably better
10
+ off sticking with your monolith and considering microservices in the future when
11
+ the need arise or even maybe never if you'll lucky.
12
+
13
+ Microservices are not for everybody, they're hard and infact thery're not a good
14
+ solution for everybody.
15
+
16
+ Before choosing and investing in microservices architecture, I advise you to
17
+ strongly considering it from every angle.
18
+
19
+ Recommended reads/videos:
20
+
21
+ * [Microservices](http://martinfowler.com/articles/microservices.html) by Martin Fowler
22
+ * [RailsConf 2015 Keynote](https://www.youtube.com/watch?v=KJVTM7mE1Cc) by David Heinemeier Hansson (video)
23
+ * [Ruby On Ales 2015 - The Recipe for the Worlds Largest Rails Monolith](https://www.youtube.com/watch?v=naTRzjHaIhE) by Akira Matsuda (video)
24
+
25
+ ## Rails::Service Overview
26
+
27
+ If you choose to go with microservice architecture or you're already working on such application(s)
28
+
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ ```ruby
35
+ gem 'rails-service'
36
+ ```
37
+
38
+ And then execute:
39
+
40
+ $ bundle
41
+
42
+ Or install it yourself as:
43
+
44
+ $ gem install rails-service
45
+
46
+ ## Usage
47
+
48
+ TODO: Write usage instructions here
49
+
50
+ ## Todo
51
+
52
+ * Rake task to generate Rails::Service skeleton (app-manifest.yaml, app-config.yaml etc.)
53
+ * Docs
54
+ * Add app-manifest page to admin panel
55
+ * Add logging everywhere
56
+ * KV Logger
57
+ * GRPC
58
+ * Endpoint ACL (Guard Dog)
59
+ * Exception notification abstraction
60
+ * on_fork hooks abstraction
61
+ * exceptions_app for engines (not sure if it's possible to have one)
62
+
63
+ ## Development
64
+
65
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
66
+
67
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub at https://github.com/strzalek/rails-service.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
8
+
9
+ desc 'Run Rails::Service unit tests.'
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'lib'
12
+ t.libs << 'test'
13
+ t.pattern = 'test/**/*_test.rb'
14
+ t.verbose = true
15
+ t.warning = false
16
+ end
@@ -0,0 +1,32 @@
1
+ # TODO: Should this support JSON format too?
2
+ class Rails::Service::AdminController < Rails::Service::BaseController # rubocop:disable Style/ClassAndModuleChildren
3
+ if Rails::Service.config.admin_action_modules.present?
4
+ Rails::Service.config.admin_action_modules.each do |mod|
5
+ prepend mod
6
+ end
7
+ end
8
+
9
+ layout 'admin'
10
+
11
+ append_view_path Rails::Service.config.admin_view_resolvers
12
+
13
+ before_filter do
14
+ @service_context ||= Rails::Service.context
15
+ end
16
+
17
+ def environment
18
+ @env = ENV.sort
19
+ end
20
+
21
+ def routing; end
22
+
23
+ def rails_properties; end
24
+
25
+ def manifest
26
+ @manifest = Rails::Service.manifest
27
+ end
28
+
29
+ def config
30
+ @config = Rails::Service.app_config
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ class Rails::Service::BaseController < ActionController::Base # rubocop:disable Style/ClassAndModuleChildren
2
+ protect_from_forgery with: :exception
3
+ end
@@ -0,0 +1,44 @@
1
+ class Rails::Service::StatusController < Rails::Service::BaseController # rubocop:disable Style/ClassAndModuleChildren
2
+ if Rails::Service.config.status_action_modules.present?
3
+ Rails::Service.config.status_action_modules.each do |mod|
4
+ prepend mod
5
+ end
6
+ end
7
+
8
+ def index
9
+ render_status :ok, time: Time.current
10
+ end
11
+
12
+ SELECT_ONE = 'SELECT 1'.freeze
13
+
14
+ def db
15
+ begin
16
+ sql_result = nil
17
+ status = :ok
18
+ time = Benchmark.realtime { sql_result = ActiveRecord::Base.connection.execute(SELECT_ONE).first }
19
+
20
+ time = (time * 1_000).round(4)
21
+ rescue
22
+ status = :critical
23
+ end
24
+
25
+ render_status status, time: time
26
+ end
27
+
28
+ protected
29
+
30
+ STATUS_TYPES = [:ok, :warning, :critical].freeze
31
+
32
+ def render_status(status, params = {})
33
+ raise ArgumentError unless STATUS_TYPES.include?(status)
34
+
35
+ status_hash = {
36
+ status: status,
37
+ }.merge(params)
38
+
39
+ http_status = status == :critical ? :service_unavailable : :ok
40
+ response.headers['Server-Status'] = status.to_s.capitalize
41
+
42
+ render status: http_status, json: status_hash
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ module Rails
2
+ module Service
3
+ module AdminHelper
4
+ def render_sidebar
5
+ li = []
6
+ Rails::Service::AdminController.action_methods.sort.each do |method|
7
+ text = method.split('_').map(&:capitalize).join(' ')
8
+ li << content_tag(:li, link_to(text, admin_path(action: method)).html_safe)
9
+ end
10
+ content_tag(:ul, li.join.html_safe, class: 'nav nav-stacked')
11
+ end
12
+
13
+ def render_rails_iframe(opts = {})
14
+ attrs = {
15
+ name: opts.fetch(:name),
16
+ id: opts.fetch(:name),
17
+ src: opts.fetch(:src),
18
+ frameborder: '0',
19
+ scrolling: 'no',
20
+ onload: 'javascript:resizeIframe(this);',
21
+ }
22
+
23
+ content_tag(:iframe, nil, attrs)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,100 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Services</title>
5
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
6
+ <%= csrf_meta_tags %>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ padding: 0;
11
+ }
12
+
13
+ iframe {
14
+ overflow: auto;
15
+ border: 0;
16
+ width: 100%;
17
+ height: 100%;
18
+ }
19
+
20
+ .wrapper {
21
+ display: block;
22
+ width: 80%;
23
+ margin: auto;
24
+ overflow: auto;
25
+ }
26
+
27
+ #top {
28
+ color: white;
29
+ margin-bottom: 10px;
30
+ }
31
+
32
+ #top h1 {
33
+ margin-left: 160px;
34
+ }
35
+
36
+ #top li span {
37
+ text-align: right;
38
+ display: block;
39
+ float: left;
40
+ color: #d6d6d6;
41
+ width: 150px;
42
+ margin-right: 10px;
43
+ }
44
+
45
+ .production #top {
46
+ background: #CA0000; // red
47
+ }
48
+
49
+ .staging #top {
50
+ background: #518e16; // green
51
+ }
52
+
53
+ .development #top {
54
+ background: #006EFF; // blue
55
+ }
56
+
57
+ #sidebar {
58
+ width: 15%;
59
+ float: left;
60
+ }
61
+
62
+ #content {
63
+ float: left;
64
+ width: 85%;
65
+ padding-left: 10px;
66
+ }
67
+ </style>
68
+ <script language="javascript" type="text/javascript">
69
+ function resizeIframe(obj) {
70
+ obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
71
+ }
72
+ </script>
73
+ </head>
74
+ <body class="<%= Rails.env %>">
75
+ <div id="top">
76
+ <div class="wrapper">
77
+ <h1><%= @service_context.app %></h1>
78
+ <ul class="list-unstyled">
79
+ <li><span>Datacenter</span> <%= @service_context.dc %></li>
80
+ <li><span>Host</span> <%= @service_context.host %></li>
81
+ <li><span>Environment</span> <%= @service_context.env %></li>
82
+ <li><span>PID</span> <%= @service_context.pid %></li>
83
+ <li><span>Revision</span> <%= @service_context.rev %></li>
84
+ </ul>
85
+ </div>
86
+ </div>
87
+
88
+ <div id="page">
89
+ <div class="wrapper">
90
+ <div id="sidebar">
91
+ <%= render_sidebar %>
92
+ </div>
93
+
94
+ <div id="content">
95
+ <%= yield %>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </body>
100
+ </html>