apisonator 2.100.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 (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)