apisonator 2.100.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +317 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.base +65 -0
  5. data/Gemfile.lock +319 -0
  6. data/Gemfile.on_prem +1 -0
  7. data/Gemfile.on_prem.lock +297 -0
  8. data/LICENSE +202 -0
  9. data/NOTICE +15 -0
  10. data/README.md +230 -0
  11. data/Rakefile +287 -0
  12. data/apisonator.gemspec +47 -0
  13. data/app/api/api.rb +13 -0
  14. data/app/api/internal/alert_limits.rb +32 -0
  15. data/app/api/internal/application_keys.rb +49 -0
  16. data/app/api/internal/application_referrer_filters.rb +43 -0
  17. data/app/api/internal/applications.rb +77 -0
  18. data/app/api/internal/errors.rb +54 -0
  19. data/app/api/internal/events.rb +42 -0
  20. data/app/api/internal/internal.rb +104 -0
  21. data/app/api/internal/metrics.rb +40 -0
  22. data/app/api/internal/service_tokens.rb +46 -0
  23. data/app/api/internal/services.rb +58 -0
  24. data/app/api/internal/stats.rb +42 -0
  25. data/app/api/internal/usagelimits.rb +62 -0
  26. data/app/api/internal/utilization.rb +23 -0
  27. data/bin/3scale_backend +223 -0
  28. data/bin/3scale_backend_worker +26 -0
  29. data/config.ru +4 -0
  30. data/config/puma.rb +192 -0
  31. data/config/schedule.rb +9 -0
  32. data/ext/mkrf_conf.rb +64 -0
  33. data/lib/3scale/backend.rb +67 -0
  34. data/lib/3scale/backend/alert_limit.rb +56 -0
  35. data/lib/3scale/backend/alerts.rb +137 -0
  36. data/lib/3scale/backend/analytics/kinesis.rb +3 -0
  37. data/lib/3scale/backend/analytics/kinesis/adapter.rb +180 -0
  38. data/lib/3scale/backend/analytics/kinesis/exporter.rb +86 -0
  39. data/lib/3scale/backend/analytics/kinesis/job.rb +135 -0
  40. data/lib/3scale/backend/analytics/redshift.rb +3 -0
  41. data/lib/3scale/backend/analytics/redshift/adapter.rb +367 -0
  42. data/lib/3scale/backend/analytics/redshift/importer.rb +83 -0
  43. data/lib/3scale/backend/analytics/redshift/job.rb +33 -0
  44. data/lib/3scale/backend/application.rb +330 -0
  45. data/lib/3scale/backend/application_events.rb +76 -0
  46. data/lib/3scale/backend/background_job.rb +65 -0
  47. data/lib/3scale/backend/configurable.rb +20 -0
  48. data/lib/3scale/backend/configuration.rb +151 -0
  49. data/lib/3scale/backend/configuration/loader.rb +42 -0
  50. data/lib/3scale/backend/constants.rb +19 -0
  51. data/lib/3scale/backend/cors.rb +84 -0
  52. data/lib/3scale/backend/distributed_lock.rb +67 -0
  53. data/lib/3scale/backend/environment.rb +21 -0
  54. data/lib/3scale/backend/error_storage.rb +52 -0
  55. data/lib/3scale/backend/errors.rb +343 -0
  56. data/lib/3scale/backend/event_storage.rb +120 -0
  57. data/lib/3scale/backend/experiment.rb +84 -0
  58. data/lib/3scale/backend/extensions.rb +5 -0
  59. data/lib/3scale/backend/extensions/array.rb +19 -0
  60. data/lib/3scale/backend/extensions/hash.rb +26 -0
  61. data/lib/3scale/backend/extensions/nil_class.rb +13 -0
  62. data/lib/3scale/backend/extensions/redis.rb +44 -0
  63. data/lib/3scale/backend/extensions/string.rb +13 -0
  64. data/lib/3scale/backend/extensions/time.rb +110 -0
  65. data/lib/3scale/backend/failed_jobs_scheduler.rb +141 -0
  66. data/lib/3scale/backend/job_fetcher.rb +122 -0
  67. data/lib/3scale/backend/listener.rb +728 -0
  68. data/lib/3scale/backend/listener_metrics.rb +99 -0
  69. data/lib/3scale/backend/logging.rb +48 -0
  70. data/lib/3scale/backend/logging/external.rb +44 -0
  71. data/lib/3scale/backend/logging/external/impl.rb +93 -0
  72. data/lib/3scale/backend/logging/external/impl/airbrake.rb +66 -0
  73. data/lib/3scale/backend/logging/external/impl/bugsnag.rb +69 -0
  74. data/lib/3scale/backend/logging/external/impl/default.rb +18 -0
  75. data/lib/3scale/backend/logging/external/resque.rb +57 -0
  76. data/lib/3scale/backend/logging/logger.rb +18 -0
  77. data/lib/3scale/backend/logging/middleware.rb +62 -0
  78. data/lib/3scale/backend/logging/middleware/json_writer.rb +21 -0
  79. data/lib/3scale/backend/logging/middleware/text_writer.rb +60 -0
  80. data/lib/3scale/backend/logging/middleware/writer.rb +143 -0
  81. data/lib/3scale/backend/logging/worker.rb +107 -0
  82. data/lib/3scale/backend/manifest.rb +80 -0
  83. data/lib/3scale/backend/memoizer.rb +277 -0
  84. data/lib/3scale/backend/metric.rb +275 -0
  85. data/lib/3scale/backend/metric/collection.rb +91 -0
  86. data/lib/3scale/backend/oauth.rb +4 -0
  87. data/lib/3scale/backend/oauth/token.rb +26 -0
  88. data/lib/3scale/backend/oauth/token_key.rb +30 -0
  89. data/lib/3scale/backend/oauth/token_storage.rb +313 -0
  90. data/lib/3scale/backend/oauth/token_value.rb +25 -0
  91. data/lib/3scale/backend/period.rb +3 -0
  92. data/lib/3scale/backend/period/boundary.rb +107 -0
  93. data/lib/3scale/backend/period/cache.rb +28 -0
  94. data/lib/3scale/backend/period/period.rb +402 -0
  95. data/lib/3scale/backend/queue_storage.rb +16 -0
  96. data/lib/3scale/backend/rack.rb +49 -0
  97. data/lib/3scale/backend/rack/exception_catcher.rb +136 -0
  98. data/lib/3scale/backend/rack/internal_error_catcher.rb +23 -0
  99. data/lib/3scale/backend/rack/prometheus.rb +19 -0
  100. data/lib/3scale/backend/saas.rb +6 -0
  101. data/lib/3scale/backend/saas_analytics.rb +4 -0
  102. data/lib/3scale/backend/server.rb +30 -0
  103. data/lib/3scale/backend/server/falcon.rb +52 -0
  104. data/lib/3scale/backend/server/puma.rb +71 -0
  105. data/lib/3scale/backend/service.rb +317 -0
  106. data/lib/3scale/backend/service_token.rb +97 -0
  107. data/lib/3scale/backend/stats.rb +8 -0
  108. data/lib/3scale/backend/stats/aggregator.rb +170 -0
  109. data/lib/3scale/backend/stats/aggregators/base.rb +72 -0
  110. data/lib/3scale/backend/stats/aggregators/response_code.rb +58 -0
  111. data/lib/3scale/backend/stats/aggregators/usage.rb +34 -0
  112. data/lib/3scale/backend/stats/bucket_reader.rb +135 -0
  113. data/lib/3scale/backend/stats/bucket_storage.rb +108 -0
  114. data/lib/3scale/backend/stats/cleaner.rb +195 -0
  115. data/lib/3scale/backend/stats/codes_commons.rb +14 -0
  116. data/lib/3scale/backend/stats/delete_job_def.rb +60 -0
  117. data/lib/3scale/backend/stats/key_generator.rb +73 -0
  118. data/lib/3scale/backend/stats/keys.rb +104 -0
  119. data/lib/3scale/backend/stats/partition_eraser_job.rb +58 -0
  120. data/lib/3scale/backend/stats/partition_generator_job.rb +46 -0
  121. data/lib/3scale/backend/stats/period_commons.rb +34 -0
  122. data/lib/3scale/backend/stats/stats_parser.rb +141 -0
  123. data/lib/3scale/backend/stats/storage.rb +113 -0
  124. data/lib/3scale/backend/statsd.rb +14 -0
  125. data/lib/3scale/backend/storable.rb +35 -0
  126. data/lib/3scale/backend/storage.rb +40 -0
  127. data/lib/3scale/backend/storage_async.rb +4 -0
  128. data/lib/3scale/backend/storage_async/async_redis.rb +21 -0
  129. data/lib/3scale/backend/storage_async/client.rb +205 -0
  130. data/lib/3scale/backend/storage_async/pipeline.rb +79 -0
  131. data/lib/3scale/backend/storage_async/resque_extensions.rb +30 -0
  132. data/lib/3scale/backend/storage_helpers.rb +278 -0
  133. data/lib/3scale/backend/storage_key_helpers.rb +9 -0
  134. data/lib/3scale/backend/storage_sync.rb +43 -0
  135. data/lib/3scale/backend/transaction.rb +62 -0
  136. data/lib/3scale/backend/transactor.rb +177 -0
  137. data/lib/3scale/backend/transactor/limit_headers.rb +54 -0
  138. data/lib/3scale/backend/transactor/notify_batcher.rb +139 -0
  139. data/lib/3scale/backend/transactor/notify_job.rb +47 -0
  140. data/lib/3scale/backend/transactor/process_job.rb +33 -0
  141. data/lib/3scale/backend/transactor/report_job.rb +84 -0
  142. data/lib/3scale/backend/transactor/status.rb +236 -0
  143. data/lib/3scale/backend/transactor/usage_report.rb +182 -0
  144. data/lib/3scale/backend/usage.rb +63 -0
  145. data/lib/3scale/backend/usage_limit.rb +115 -0
  146. data/lib/3scale/backend/use_cases/provider_key_change_use_case.rb +60 -0
  147. data/lib/3scale/backend/util.rb +17 -0
  148. data/lib/3scale/backend/validators.rb +26 -0
  149. data/lib/3scale/backend/validators/base.rb +36 -0
  150. data/lib/3scale/backend/validators/key.rb +17 -0
  151. data/lib/3scale/backend/validators/limits.rb +57 -0
  152. data/lib/3scale/backend/validators/oauth_key.rb +15 -0
  153. data/lib/3scale/backend/validators/oauth_setting.rb +15 -0
  154. data/lib/3scale/backend/validators/redirect_uri.rb +33 -0
  155. data/lib/3scale/backend/validators/referrer.rb +60 -0
  156. data/lib/3scale/backend/validators/service_state.rb +15 -0
  157. data/lib/3scale/backend/validators/state.rb +15 -0
  158. data/lib/3scale/backend/version.rb +5 -0
  159. data/lib/3scale/backend/views/oauth_access_tokens.builder +14 -0
  160. data/lib/3scale/backend/views/oauth_app_id_by_token.builder +4 -0
  161. data/lib/3scale/backend/worker.rb +87 -0
  162. data/lib/3scale/backend/worker_async.rb +88 -0
  163. data/lib/3scale/backend/worker_metrics.rb +44 -0
  164. data/lib/3scale/backend/worker_sync.rb +32 -0
  165. data/lib/3scale/bundler_shim.rb +17 -0
  166. data/lib/3scale/prometheus_server.rb +10 -0
  167. data/lib/3scale/tasks/connectivity.rake +41 -0
  168. data/lib/3scale/tasks/helpers.rb +3 -0
  169. data/lib/3scale/tasks/helpers/environment.rb +23 -0
  170. data/lib/3scale/tasks/stats.rake +131 -0
  171. data/lib/3scale/tasks/swagger.rake +46 -0
  172. data/licenses.xml +1215 -0
  173. metadata +227 -0
@@ -0,0 +1,40 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/services/:service_id/metrics' do
5
+ get '/:id' do |service_id, id|
6
+ metric = Metric.load service_id, id
7
+ if metric
8
+ { status: :found, metric: metric.to_hash }.to_json
9
+ else
10
+ [404, headers, { status: :not_found, error: 'metric not found' }.to_json]
11
+ end
12
+ end
13
+
14
+ post '/:id' do |service_id, id|
15
+ metric_attrs = api_params Metric
16
+ metric_attrs[:service_id] = service_id
17
+ metric_attrs[:id] = id
18
+ metric = Metric.save metric_attrs
19
+ [201, headers, { status: :created, metric: metric.to_hash }.to_json]
20
+ end
21
+
22
+ put '/:id' do |service_id, id|
23
+ metric_attrs = api_params Metric
24
+ metric_attrs[:service_id] = service_id
25
+ metric_attrs[:id] = id
26
+ metric = Metric.save metric_attrs
27
+ { status: :modified, metric: metric.to_hash }.to_json
28
+ end
29
+
30
+ delete '/:id' do |service_id, id|
31
+ if Metric.delete(service_id, id)
32
+ { status: :deleted }.to_json
33
+ else
34
+ [404, headers, { status: :not_found, error: 'metric not found' }.to_json]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/service_tokens' do
5
+
6
+ head '/:token/:service_id/' do |token, service_id|
7
+ ServiceToken.exists?(token, service_id) ? 200 : 404
8
+ end
9
+
10
+ post '/' do
11
+ check_tokens_param!
12
+
13
+ token_pairs = @service_tokens.map do |token, token_info|
14
+ { service_token: token, service_id: token_info[:service_id] }
15
+ end
16
+
17
+ begin
18
+ ServiceToken.save_pairs(token_pairs)
19
+ [201, headers, { status: :created }.to_json]
20
+ rescue ServiceToken::ValidationError => e
21
+ halt(e.http_code, { status: :error, error: e.message }.to_json)
22
+ end
23
+ end
24
+
25
+ delete '/' do
26
+ check_tokens_param!
27
+
28
+ deleted = @service_tokens.count do |token|
29
+ ServiceToken.delete(token[:service_token], token[:service_id]) == 1
30
+ end
31
+
32
+ { status: :deleted, count: deleted }.to_json
33
+ end
34
+
35
+ private
36
+
37
+ def check_tokens_param!
38
+ @service_tokens = params[:service_tokens]
39
+ unless @service_tokens
40
+ halt(400, { error: "missing parameter 'service_tokens'".freeze }.to_json)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,58 @@
1
+ require '3scale/backend/use_cases/provider_key_change_use_case'
2
+
3
+ module ThreeScale
4
+ module Backend
5
+ module API
6
+ internal_api '/services' do
7
+ get '/:id' do
8
+ service = Service.load_by_id(params[:id])
9
+ if service
10
+ { status: :found, service: service.to_hash }.to_json
11
+ else
12
+ [404, headers, {error: :not_found}.to_json]
13
+ end
14
+ end
15
+
16
+ post '/' do
17
+ svc_attrs = api_params Service
18
+ service = Service.save!(svc_attrs)
19
+ [201, headers, {service: service.to_hash, status: :created}.to_json]
20
+ end
21
+
22
+ put '/:id' do
23
+ svc_attrs = api_params Service
24
+ service = Service.load_by_id(params[:id])
25
+ if service
26
+ svc_attrs.each do |attr, value|
27
+ service.send "#{attr}=", value
28
+ end
29
+ service.save!
30
+ else
31
+ service = Service.save!(svc_attrs)
32
+ end
33
+ {service: service.to_hash, status: :ok}.to_json
34
+ end
35
+
36
+ put '/change_provider_key/:key' do
37
+ begin
38
+ ProviderKeyChangeUseCase.new(params[:key], params[:new_key]).process
39
+ {status: :ok}.to_json
40
+ rescue InvalidProviderKeys, ProviderKeyExists, ProviderKeyNotFound => e
41
+ respond_with_400 e
42
+ end
43
+ end
44
+
45
+ delete '/:id' do
46
+ begin
47
+ Service.delete_by_id params[:id]
48
+ {status: :deleted}.to_json
49
+ rescue ServiceIsDefaultService => e
50
+ respond_with_400 e
51
+ rescue ServiceIdInvalid => e
52
+ respond_with_404 e
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,42 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/services/:service_id/stats' do
5
+ before do
6
+ respond_with_404('service not found') unless Service.exists?(params[:service_id])
7
+ end
8
+
9
+ # This is very slow and needs to be disabled until the performance
10
+ # issues are solved. In the meanwhile, the job will just return OK.
11
+ =begin
12
+ delete '' do |service_id|
13
+ delete_stats_job_attrs = api_params Stats::DeleteJobDef
14
+ delete_stats_job_attrs[:service_id] = service_id
15
+ delete_stats_job_attrs[:from] = delete_stats_job_attrs[:from].to_i
16
+ delete_stats_job_attrs[:to] = delete_stats_job_attrs[:to].to_i
17
+ begin
18
+ Stats::DeleteJobDef.new(delete_stats_job_attrs).run_async
19
+ rescue DeleteServiceStatsValidationError => e
20
+ [400, headers, { status: :error, error: e.message }.to_json]
21
+ else
22
+ { status: :to_be_deleted }.to_json
23
+ end
24
+ =end
25
+
26
+ # This is an alternative to the above. It just adds the service to a
27
+ # Redis set to marked is as "to be deleted".
28
+ # Later a script can read that set and actually delete the keys.
29
+ # Read the docs of the Stats::Cleaner class for more details.
30
+ #
31
+ # Notice that this method ignores the "from" and "to" parameters. When
32
+ # system calls this method, they're always interested in deleting all
33
+ # the keys. They were just passing "from" and "to" to make the
34
+ # implementation of the option above easier.
35
+ delete '' do |service_id|
36
+ Stats::Cleaner.mark_service_to_be_deleted(service_id)
37
+ { status: :to_be_deleted }.to_json
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,62 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ # Note: ideally this URL should NOT look like this.
5
+ #
6
+ # We have it this way because the entities don't fit a hierarchical
7
+ # scheme since their relations are complex:
8
+ #
9
+ # * We don't have UsageLimit ID's per se
10
+ # * Plan is a denormalized entity in backend
11
+ # * Metrics need to be loaded from a given Service
12
+ # * But neither Plan nor Metric are nested wrt each other
13
+ # * And Service has no other use than being able to load a Metric
14
+ #
15
+ # In the end no single URL shape is pleasing enough: specifying some
16
+ # needed IDs as parameters feels wrong because of the reasons above, but
17
+ # adding them to the URL makes for really long URLs with no clear
18
+ # hierarchy for nesting. We chose the latter, but could have chosen almost
19
+ # any workable form.
20
+ #
21
+ internal_api '/services/:service_id/plans/:plan_id/usagelimits' do
22
+ module UsageLimitsHelper
23
+ def self.to_hash(service_id, plan_id, metric_id, period, value)
24
+ {
25
+ :service_id => service_id,
26
+ :plan_id => plan_id,
27
+ :metric_id => metric_id,
28
+ period.to_sym => value
29
+ }
30
+ end
31
+ end
32
+
33
+ get '/:metric_id/:period' do |service_id, plan_id, metric_id, period|
34
+ value = UsageLimit.load_value(service_id, plan_id, metric_id, period)
35
+ if value
36
+ { status: :found, usagelimit: UsageLimitsHelper.to_hash(service_id, plan_id,
37
+ metric_id, period,
38
+ value) }.to_json
39
+ else
40
+ [404, headers, { status: :not_found, error: 'usagelimit not found' }.to_json]
41
+ end
42
+ end
43
+
44
+ put '/:metric_id/:period' do |service_id, plan_id, metric_id, period|
45
+ attributes = params[:usagelimit]
46
+ halt 400, { status: :error, error: 'missing parameter \'usagelimit\'' }.to_json unless attributes
47
+ value = attributes[period.to_sym]
48
+ halt 400, { status: :error, error: "missing parameter '#{period}'" }.to_json unless value
49
+ ul_hash = UsageLimitsHelper.to_hash(service_id, plan_id, metric_id, period, value)
50
+ UsageLimit.save(ul_hash)
51
+ { status: :modified, usagelimit: ul_hash }.to_json
52
+ end
53
+
54
+ delete '/:metric_id/:period' do |service_id, plan_id, metric_id, period|
55
+ UsageLimit.delete(service_id, plan_id, metric_id, period)
56
+ { status: :deleted }.to_json
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,23 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/services/:service_id/applications/:app_id/utilization' do
5
+ before do
6
+ unless Service.exists?(params[:service_id])
7
+ respond_with_404('service not found')
8
+ end
9
+
10
+ unless Application.exists?(params[:service_id], params[:app_id])
11
+ respond_with_404('application not found')
12
+ end
13
+ end
14
+
15
+ get '/' do |service_id, app_id|
16
+ utilization = Transactor.utilization(service_id, app_id)
17
+ usage_reports = utilization.map(&:to_h)
18
+ { status: :found, utilization: usage_reports }.to_json
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env ruby
2
+ require 'gli'
3
+ require '3scale/backend/version'
4
+
5
+ class Runner
6
+ class << self
7
+ def do_exit(code, global, msg='Unknown error')
8
+ Dir.chdir global[:original_dir]
9
+ exit_now! msg, code
10
+ end
11
+
12
+ def verbose(global_options, out=STDOUT)
13
+ out.puts(yield) if global_options[:verbose] || global_options[:'dry-run']
14
+ end
15
+
16
+ def exec(global_options)
17
+ Process.exec(*yield) unless global_options[:'dry-run']
18
+ end
19
+
20
+
21
+ def build_cmdline(cmd, global_options, options, args)
22
+ require '3scale/backend/server'
23
+ server = ThreeScale::Backend::Server.get global_options[:server]
24
+ server.send(cmd, global_options, options, args)
25
+ rescue => e
26
+ STDERR.puts "Error: #{e.message}#{"\n" + caller_locations(0).join("\n") if global_options[:verbose]}"
27
+ end
28
+
29
+ def do_command(cmd, global_options, options, args)
30
+ argv = build_cmdline cmd, global_options, options, args
31
+ do_exit 1, global_options, "can't build command line" unless argv
32
+ argv << global_options[:'extra-args'] if global_options[:'extra-args']
33
+ verbose(global_options) { "Executing: #{argv.join ' '}" }
34
+ exec(global_options) { argv }
35
+ end
36
+
37
+ def add_instance_id_options(c)
38
+ c.desc 'TCP port number where backend listens for connections'
39
+ c.arg_name 'NUMBER'
40
+ c.default_value '3000'
41
+ c.flag :p, :port
42
+ c.desc 'Filename where backend writes its PID'
43
+ c.arg_name 'FILENAME'
44
+ c.flag :pidfile
45
+ end
46
+ end
47
+
48
+ extend GLI::App
49
+
50
+ program_desc '3scale_backend launcher'
51
+
52
+ version ThreeScale::Backend::VERSION
53
+
54
+ CONFIG_FILE = '.backend_launcher.rc.yml'
55
+ EXPANDED_ROOT_PATH = File.expand_path(File.join('..', '..'), __FILE__)
56
+
57
+ config_file File.join(ENV['HOME'] || File.join('', 'tmp'), CONFIG_FILE)
58
+
59
+ subcommand_option_handling :normal
60
+ arguments :strict
61
+
62
+ desc 'Load Bundler when running'
63
+ default_value true
64
+ switch :b, :bundler
65
+
66
+ desc 'Do not actually run anything, just print what would be done'
67
+ default_value false
68
+ switch :n, :'dry-run'
69
+
70
+ desc 'Verbose mode'
71
+ default_value false
72
+ switch :v, :verbose
73
+
74
+ desc 'Directory where the app server will expect the code to be at'
75
+ arg_name 'DIRNAME'
76
+ flag :z, :directory
77
+
78
+ desc "Application server to use with backend"
79
+ default_value 'puma'
80
+ arg_name 'SERVER'
81
+ flag :s, :server
82
+
83
+ desc 'Environment backend will use'
84
+ arg_name 'ENVIRONMENT'
85
+ default_value 'development'
86
+ flag :e, :environment
87
+
88
+ desc 'Extra command arguments'
89
+ arg_name 'ARGS'
90
+ flag :X, :'extra-args'
91
+
92
+ pre do |global, command, options, args|
93
+ # Pre logic here
94
+ # Return true to proceed; false to abort and not call the
95
+ # chosen command
96
+ # Use skips_pre before a command to skip this block
97
+ # on that command only
98
+ global[:original_dir] = Dir.pwd
99
+ if global[:directory]
100
+ Dir.chdir global[:directory]
101
+ end
102
+ if global[:bundler]
103
+ begin
104
+ require 'bundler/setup'
105
+ if !Bundler::SharedHelpers.in_bundle?
106
+ # Gemfile not found, try with relative Gemfile from us
107
+ ENV['BUNDLE_GEMFILE'] = File.join(EXPANDED_ROOT_PATH, 'Gemfile')
108
+ require 'bundler'
109
+ Bundler.setup
110
+ end
111
+ rescue LoadError, Bundler::BundlerError => e
112
+ do_exit 64, global, "Unable to meet requirements: #{e.message}"
113
+ end
114
+ end
115
+ # manifest loading is not strictly necessary, so make it optional
116
+ begin
117
+ require '3scale/backend/manifest'
118
+ global[:manifest] = ThreeScale::Backend::Manifest.report
119
+ rescue LoadError, NameError, NoMethodError
120
+ end
121
+ true
122
+ end
123
+
124
+ post do |global,command,options,args|
125
+ # Post logic here
126
+ # Use skips_post before a command to skip this
127
+ # block on that command only
128
+ Dir.chdir global[:original_dir]
129
+ end
130
+
131
+ on_error do |exception|
132
+ # Error logic here
133
+ # return false to skip default error handling
134
+ true
135
+ end
136
+
137
+ desc 'Shows the capabilities of backend in its manifest'
138
+ command :manifest do |c|
139
+ c.action do |global_options, options, arg|
140
+ manifest = global_options[:manifest]
141
+ do_exit 65, global_options, "Could not load manifest: #{e.message}" unless manifest
142
+ STDOUT.puts(manifest.map do |k, v|
143
+ "#{"#{k[0..19]}:".ljust(21)} #{v.inspect}"
144
+ end.join "\n")
145
+ end
146
+ end
147
+
148
+ desc 'Starts the backend server'
149
+ command :start do |c|
150
+ c.desc 'Filename where backend will log requests to (default: stdout)'
151
+ c.arg_name 'FILENAME'
152
+ c.flag :l, :logfile
153
+ c.desc 'Filename where backend will log errors to, defaulting to --logfile value'
154
+ c.arg_name 'FILENAME'
155
+ c.flag :x, :errorfile
156
+ c.desc 'Daemonize the server'
157
+ c.default_value false
158
+ c.switch :d, :daemonize
159
+ add_instance_id_options c
160
+
161
+ c.action do |global_options, options, args|
162
+ options[:logfile] = nil if options[:logfile] == '-'
163
+ options[:errorfile] ||= options[:logfile]
164
+ options[:errorfile] = nil if options[:errorfile] == '-'
165
+ do_command :start, global_options, options, args
166
+ end
167
+
168
+ c.example '3scale_backend start -p 5001 -d --pidfile backend.pid -l /var/log/backend.log -x /var/log/backend.err.log',
169
+ desc: 'Listen on port 5001, daemonize with pidfile, write separate logs for requests and errors'
170
+ end
171
+
172
+ desc 'Stops the backend server'
173
+ command :stop do |c|
174
+ add_instance_id_options c
175
+
176
+ c.action do |global_options, options, args|
177
+ do_command :stop, global_options, options, args
178
+ end
179
+
180
+ c.example '3scale_backend stop --pidfile backend.pid', desc: 'Stop a daemon with a pidfile'
181
+ end
182
+
183
+ desc 'Restarts the backend server'
184
+ command :restart do |c|
185
+ add_instance_id_options c
186
+
187
+ c.desc 'Perform a phased-restart where available to avoid downtime'
188
+ c.default_value true
189
+ c.switch :"phased-restart"
190
+
191
+ c.action do |global_options, options, args|
192
+ do_command :restart, global_options, options, args
193
+ end
194
+ end
195
+
196
+ desc 'Prints the status of the backend server'
197
+ command :status do |c|
198
+ add_instance_id_options c
199
+
200
+ c.action do |global_options, options, args|
201
+ do_command :status, global_options, options, args
202
+ end
203
+ end
204
+
205
+ desc 'Prints statistics of the backend server'
206
+ command :stats do |c|
207
+ add_instance_id_options c
208
+
209
+ c.action do |global_options, options, args|
210
+ do_command :stats, global_options, options, args
211
+ end
212
+ end
213
+
214
+ desc 'Print extra help from the application server'
215
+ command :'help-server' do |c|
216
+ c.action do |global_options, options, args|
217
+ server = ThreeScale::Backend::Server.get global_options[:server]
218
+ server.help(global_options, options, args)
219
+ end
220
+ end
221
+ end
222
+
223
+ exit Runner.run(ARGV)