ct-register-microservice 1.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2ce4f0bb7836b0cb9101620a3c7bfbf8d03f9a6d13f67d0a405e8aee8732cf0c
4
+ data.tar.gz: 5d8195652a1dd84df8e2fcd0fe1a3cbd1d6a23b9283d445331e6b7b0836283a4
5
+ SHA512:
6
+ metadata.gz: 2c65951b30712b860cad39bebbb464e257c6233ffbbe553c68efda8a2cb9f7000540c0ed3ec66679022dd7ff17d78f7470f46e217e7f079e4e7aa6d84af56aeb
7
+ data.tar.gz: 9600acc940b55a5b574d1c98da6f7ce00a4398fec41b85c43c76a79693a0797314f7db696340df4be9e4c559c968c1e8e57588a11b3eff178a5e5200dd169343
@@ -0,0 +1,65 @@
1
+ # Control Tower registration Rails engine
2
+
3
+ Rails engine that integrates your rails-build microservices with [Control Tower](https://github.com/control-tower/control-tower)
4
+
5
+ [![Build Status](https://travis-ci.org/control-tower/ct-register-microservice-rails.svg?branch=master)](https://travis-ci.org/control-tower/ct-register-microservice-rails)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/85eeb71033246c5c259d/test_coverage)](https://codeclimate.com/github/control-tower/ct-register-microservice-rails/test_coverage)
7
+
8
+ ## Installation
9
+
10
+ Installing using `bundler` is recommended:
11
+
12
+ ```ruby
13
+ # Gemfile
14
+
15
+ gem 'ct-register-microservice-rails'
16
+ ```
17
+
18
+ And then execute:
19
+ ```bash
20
+ $ bundle install
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ Create a Rails initializer to define your connection settings and connect to Control Tower.
26
+ ```ruby
27
+ #config/initializers/ct_register_microservice.rb
28
+ CtRegisterMicroservice.configure do |config|
29
+ config.ct_url = 'http://your-control-tower-url.com'
30
+ config.url = 'http://your-rails-microservice-url.com'
31
+ config.ct_token = 'Control Tower auth token'
32
+ config.swagger = __dir__ + 'path/to/your/CT/registration/json/file'
33
+ config.name = 'Name of your microservice'
34
+ end
35
+ ```
36
+
37
+ After the configuration values are defined, use the following code to have your microservice register itself on Control Tower:
38
+
39
+ ```ruby
40
+ ct_connection = CtRegisterMicroservice::ControlTower.new()
41
+ ct_connection.register_service()
42
+ ```
43
+
44
+ Keep in mind that this registration process will result in Control Tower contacting your Rails server almost immediately.
45
+ Using it in Rails initializers will trigger it *before* the Rails HTTP server is up, causing the registration process to fail.
46
+
47
+ For this purpose, this engine also includes a Rake task that can be used to trigger this registration process:
48
+
49
+ ```bash
50
+ rake ct_register_microservice:register
51
+ ```
52
+
53
+
54
+ ## Current methods
55
+
56
+ This engine currently implements two convenience methods:
57
+
58
+ - `register_microservice()` registers the current Rails microservice on Control Tower. Is currently full-featured and supported
59
+ - `microservice_request()` makes a request to a different microservice within the CT environment. Currently in development, may not work as expected
60
+
61
+ ## Contributing
62
+ Feel free to contribute, pull requests are welcome.
63
+
64
+ ## License
65
+ The engine is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,28 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ load 'lib/tasks/ct_register_microservice.rake'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'CtRegisterMicroservice'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+
23
+ load 'rails/tasks/statistics.rake'
24
+
25
+
26
+
27
+ require 'bundler/gem_tasks'
28
+
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/ct_register_microservice .js
2
+ //= link_directory ../stylesheets/ct_register_microservice .css
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,5 @@
1
+ module CtRegisterMicroservice
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ require_dependency "ct_register_microservice/application_controller"
2
+
3
+ module CtRegisterMicroservice
4
+ class InfoController < ApplicationController
5
+ def info
6
+ if CtRegisterMicroservice.config.swagger and File.exist?(CtRegisterMicroservice.config.swagger)
7
+ @docs = MultiJson.load(File.read(CtRegisterMicroservice.config.swagger))
8
+ render json: @docs
9
+ else
10
+ render json: { success: false, message: 'Could not load info file' }, status: 500
11
+ end
12
+ end
13
+
14
+ def ping
15
+ render json: { success: true, message: CtRegisterMicroservice.config.name }, status: 200
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module CtRegisterMicroservice
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module CtRegisterMicroservice
2
+ module InfoHelper
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Ct register microservice</title>
5
+ <%= stylesheet_link_tag "ct_register_microservice/application", media: "all" %>
6
+ <%= javascript_include_tag "ct_register_microservice/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,4 @@
1
+ CtRegisterMicroservice::Engine.routes.draw do
2
+ get :info, action: :info, controller: 'info'
3
+ get :ping, action: :ping, controller: 'info'
4
+ end
@@ -0,0 +1,30 @@
1
+ require 'ct_register_microservice/engine'
2
+ require 'ct_register_microservice/control_tower'
3
+ require 'ct_register_microservice/http_service'
4
+ require 'ct_register_microservice/errors'
5
+ require 'multi_json'
6
+ require 'ostruct'
7
+
8
+ module CtRegisterMicroservice
9
+ class << self
10
+ attr_accessor :http_service, :config
11
+
12
+ def configure
13
+ yield config
14
+ end
15
+
16
+ def config
17
+ @config ||= OpenStruct.new
18
+ end
19
+ end
20
+
21
+ def self.http_service=(service)
22
+ @http_service = service
23
+ end
24
+
25
+ def self.make_request(options, credentials = {})
26
+ http_service.make_request(options, credentials)
27
+ end
28
+
29
+ self.http_service = HTTPService
30
+ end
@@ -0,0 +1,85 @@
1
+ require 'ct_register_microservice/errors'
2
+
3
+ module CtRegisterMicroservice
4
+ class ControlTower
5
+ def initialize
6
+ if CtRegisterMicroservice.config.ct_url.nil?
7
+ raise MissingConfigError, 'Could not register microservice - No Control Tower URL defined'
8
+ end
9
+ if CtRegisterMicroservice.config.url.nil?
10
+ raise MissingConfigError, 'Could not register microservice - No self URL defined'
11
+ end
12
+ if CtRegisterMicroservice.config.ct_token.nil?
13
+ raise MissingConfigError, 'Could not register microservice - No Control Tower auth token found'
14
+ end
15
+ if CtRegisterMicroservice.config.swagger.nil?
16
+ raise MissingConfigError, 'Could not register microservice - No swagger file defined'
17
+ end
18
+ if !File.exist?(CtRegisterMicroservice.config.swagger)
19
+ raise MissingConfigError, 'Could not register microservice - Swagger file path ' + File.absolute_path(CtRegisterMicroservice.config.swagger) + 'does not match a file'
20
+ end
21
+ if CtRegisterMicroservice.config.name.nil?
22
+ raise MissingConfigError, 'Could not register microservice - Microservice name not defined'
23
+ end
24
+
25
+ @options = OpenStruct.new
26
+ end
27
+
28
+ attr_reader :credentials, :options, :response, :ct_url, :swagger, :name, :url
29
+
30
+ def register_service(active = true)
31
+ options.http_method = "post"
32
+ options.endpoint = "/api/v1/microservice"
33
+ options.query_string = false
34
+ options.body = {
35
+ name: CtRegisterMicroservice.config.name,
36
+ url: CtRegisterMicroservice.config.url,
37
+ active: !!active
38
+ }.to_json
39
+ result = make_call(options)
40
+ result
41
+ end
42
+
43
+ # TODO: make sure it works as intended, add unit tests
44
+ def microservice_request(uri, method, headers = {}, body = nil)
45
+ options.http_method = method
46
+ options.endpoint = uri
47
+ options.headers = headers
48
+ options.headers['Authentication'] = CtRegisterMicroservice.config.ct_token
49
+ options.body = body
50
+ result = make_call(options)
51
+ result
52
+ end
53
+
54
+ def initialize_options
55
+ @options = OpenStruct.new
56
+ end
57
+
58
+ private
59
+
60
+ def make_call(options)
61
+ result = CtRegisterMicroservice.make_request(options, credentials)
62
+ unless check_errors(result.status.to_i, result.body)
63
+ MultiJson.load("[#{result.body.to_s}]")[0]
64
+ end
65
+ initialize_options
66
+ @response = result.body
67
+ end
68
+
69
+ def check_errors(status, body)
70
+ case status
71
+ when 500
72
+ initialize_options
73
+ raise CtRegisterMicroservice::ServerError.new(status, body)
74
+ when 401
75
+ initialize_options
76
+ raise CtRegisterMicroservice::NoTokenError.new(status, body)
77
+ when 404
78
+ initialize_options
79
+ raise CtRegisterMicroservice::NotFoundError.new(status, body)
80
+ else
81
+ return false
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,11 @@
1
+ require 'ct_register_microservice'
2
+
3
+ module CtRegisterMicroservice
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace CtRegisterMicroservice
6
+
7
+ config.generators do |g|
8
+ g.test_framework :rspec
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,77 @@
1
+ module CtRegisterMicroservice
2
+
3
+ class MissingConfigError < StandardError;
4
+ end
5
+
6
+ class CtRegisterMicroserviceError < StandardError;
7
+ end
8
+
9
+ class AppSecretNotDefinedError < ::CtRegisterMicroservice::CtRegisterMicroserviceError;
10
+ end
11
+
12
+ class APIError < ::CtRegisterMicroservice::CtRegisterMicroserviceError
13
+ attr_accessor :ct_error_type, :ct_error_code, :ct_error_subcode, :ct_error_message,
14
+ :ct_error_user_msg, :ct_error_user_title, :http_status, :response_body
15
+
16
+
17
+ def initialize(http_status, response_body, error_message = nil)
18
+ if response_body
19
+ self.response_body = response_body.strip
20
+ else
21
+ self.response_body = ''
22
+ end
23
+ self.http_status = http_status
24
+
25
+ if error_message && error_message.is_a?(String)
26
+ message = error_message
27
+ else
28
+ unless error_message
29
+ begin
30
+ errors = MultiJson.load(response_body) if response_body
31
+ error_array = errors['errors'].map { |n| n['detail'] } if errors.key? 'errors'
32
+ rescue
33
+ end
34
+ error_array ||= []
35
+ end
36
+
37
+ if error_array.nil? or error_array.empty?
38
+ message = self.response_body
39
+ else
40
+ message = error_array.join(', ')
41
+ end
42
+ end
43
+
44
+ super(message)
45
+ end
46
+ end
47
+
48
+ # CT returned an invalid response body
49
+ class BadCTResponse < APIError;
50
+ end
51
+
52
+ # CT responded with an error while attempting to request an access token
53
+ class OAuthTokenRequestError < APIError;
54
+ end
55
+
56
+ # Any error with a 5xx HTTP status code
57
+ class ServerError < APIError;
58
+ end
59
+
60
+ # Any error with a 4xx HTTP status code
61
+ class ClientError < APIError;
62
+ end
63
+
64
+ # All API authentication failures.
65
+ class AuthenticationError < ClientError;
66
+ end
67
+
68
+ # not found
69
+ class NotFoundError < APIError;
70
+ end
71
+
72
+ # not found
73
+ class NoTokenError < APIError;
74
+ end
75
+
76
+
77
+ end
@@ -0,0 +1,43 @@
1
+ require 'httparty'
2
+ require 'ct_register_microservice/http_service/response'
3
+ require 'ct_register_microservice/http_service/endpoint'
4
+
5
+ module CtRegisterMicroservice
6
+ module HTTPService
7
+ class << self
8
+ end
9
+
10
+ def self.make_request(options, credentials = {})
11
+ http_method = options.http_method&.to_sym || :get
12
+ url = CtRegisterMicroservice.config.ct_url
13
+ headers = options.headers || {}
14
+ headers['Content-Type'] = 'application/json' if options.http_method == 'post' || options.http_method == 'put'
15
+ endpoint = Endpoint.new(options, credentials).get
16
+ body = options.body
17
+
18
+ case http_method
19
+ when :get
20
+ response = HTTParty.get(url+endpoint, headers: headers)
21
+ when :delete
22
+ response = HTTParty.delete(url+endpoint, headers: headers)
23
+ when :post
24
+ response = HTTParty.post(url+endpoint, {
25
+ headers: headers,
26
+ body: body
27
+ })
28
+ when :put
29
+ response = HTTParty.put(url+endpoint, {
30
+ headers: headers,
31
+ body: body
32
+ })
33
+ when :patch
34
+ response = HTTParty.patch(url+endpoint, {
35
+ headers: headers,
36
+ body: body
37
+ })
38
+ end
39
+
40
+ CtRegisterMicroservice::HTTPService::Response.new(response.code.to_i, response.body, response.headers)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module CtRegisterMicroservice
2
+ module HTTPService
3
+ class Endpoint
4
+
5
+ attr_reader :options, :credentials
6
+
7
+ def initialize(options, credentials = {})
8
+ @options = options
9
+ @credentials = credentials
10
+ end
11
+
12
+ def get
13
+ endpoint_uri
14
+ end
15
+
16
+ private
17
+
18
+ def endpoint_uri
19
+ options.endpoint
20
+ end
21
+
22
+ end
23
+ end
24
+ Endpoint = HTTPService::Endpoint
25
+ end
26
+
@@ -0,0 +1,14 @@
1
+ module CtRegisterMicroservice
2
+ module HTTPService
3
+ class Response
4
+ attr_reader :status, :body, :headers
5
+
6
+ def initialize(status, body, headers)
7
+ @status = status
8
+ @body = body
9
+ @headers = headers
10
+ end
11
+ end
12
+ end
13
+ Response = HTTPService::Response
14
+ end
@@ -0,0 +1,3 @@
1
+ module CtRegisterMicroservice
2
+ VERSION = '1.3.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ namespace :ct_register_microservice do
2
+ desc 'Register microservice on configured Control Tower'
3
+ task register: [:environment] do
4
+ ct_connection = CtRegisterMicroservice::ControlTower.new()
5
+ ct_connection.register_service()
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ct-register-microservice
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Tiago Garcia
8
+ - Vizzuality
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-04-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 5.1.2
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 5.1.2
28
+ - !ruby/object:Gem::Dependency
29
+ name: httparty
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: multi_json
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: simplecov
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: simplecov-console
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: webmock
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: rspec-rails
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: sqlite3
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ description: This gem allows your Rails-built microservice to register itself on Control
141
+ Tower
142
+ email:
143
+ - info@vizzuality.com
144
+ executables: []
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - README.md
149
+ - Rakefile
150
+ - app/assets/config/ct_register_microservice_manifest.js
151
+ - app/assets/javascripts/ct_register_microservice/application.js
152
+ - app/assets/javascripts/ct_register_microservice/info.js
153
+ - app/assets/stylesheets/ct_register_microservice/application.css
154
+ - app/assets/stylesheets/ct_register_microservice/info.css
155
+ - app/controllers/ct_register_microservice/application_controller.rb
156
+ - app/controllers/ct_register_microservice/info_controller.rb
157
+ - app/helpers/ct_register_microservice/application_helper.rb
158
+ - app/helpers/ct_register_microservice/info_helper.rb
159
+ - app/views/layouts/ct_register_microservice/application.html.erb
160
+ - config/routes.rb
161
+ - lib/ct_register_microservice.rb
162
+ - lib/ct_register_microservice/control_tower.rb
163
+ - lib/ct_register_microservice/engine.rb
164
+ - lib/ct_register_microservice/errors.rb
165
+ - lib/ct_register_microservice/http_service.rb
166
+ - lib/ct_register_microservice/http_service/endpoint.rb
167
+ - lib/ct_register_microservice/http_service/response.rb
168
+ - lib/ct_register_microservice/version.rb
169
+ - lib/tasks/ct_register_microservice.rake
170
+ homepage: http://vizzuality.com
171
+ licenses:
172
+ - MIT
173
+ metadata: {}
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubyforge_project:
190
+ rubygems_version: 2.7.9
191
+ signing_key:
192
+ specification_version: 4
193
+ summary: Control Tower connector service
194
+ test_files: []