boechat 0.0.1 → 0.1.0.pre.RC1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 666155b02a02293152a1fe3ab9f25517f47c4795224d33b0e1124d2a31adb219
4
- data.tar.gz: 630e27e95ce5160648c4d4a31efa9580146ec89a9d55770b40ab2da85f85d623
3
+ metadata.gz: 60b8e03cd088bd8ac98206d892f0c9b4ade7809caaf2d7cc718f618ac6b332d8
4
+ data.tar.gz: dbe45040d76298c1583178cdb60b077b194254d8c433e9bd5ebb5595f7016f12
5
5
  SHA512:
6
- metadata.gz: b6637c22a3f0b67c59af54032c45c120ad972179a3298b996584d12c609ddd6a2898e2a1a887e693c3531076423a196a3b61777ad220ead863bae7554814b70f
7
- data.tar.gz: 1e79404dfd944972e195215b459ae3c41e4369a8b9b930f1210dcc1740e88f250878b750d2a04a47647c627c1464027c357a693b86f23c90f6c0fe04c2912c6d
6
+ metadata.gz: a41626ca7550fa8a479f4be057e5d5c696424ba808d7c8b2cd2719c09af6ba92674706d0ba5532da46f57e8014f9e026ffcd7894f5b4ed8a5a7bc4ff91fb0346
7
+ data.tar.gz: 1798b02cc56eff1c2824a6b0728b55d3c734c37ac066a34ab71292d71b7128c5ff3d560e8cd6b1b0c77e840a69cd53eef0140f3de58574b312fb4f5f2717b7cd
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.gem
2
+ .yardoc
3
+ doc/**/*
data/Gemfile.lock CHANGED
@@ -3,8 +3,8 @@ PATH
3
3
  specs:
4
4
  boechat (0.0.1)
5
5
  dry-validation (~> 0.11.1)
6
- oj (~> 3.5.0)
7
- typhoeus (~> 1.3.0)
6
+ oj (~> 3.5)
7
+ typhoeus (~> 1.3)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
@@ -43,7 +43,6 @@ GEM
43
43
  dry-equalizer (~> 0.2)
44
44
  dry-logic (~> 0.4, >= 0.4.0)
45
45
  dry-types (~> 0.12.0)
46
- dry-validation-matchers (0.4.0)
47
46
  ethon (0.11.0)
48
47
  ffi (>= 1.3.0)
49
48
  ffi (1.9.23)
@@ -89,6 +88,7 @@ GEM
89
88
  typhoeus (1.3.0)
90
89
  ethon (>= 0.9.0)
91
90
  unicode-display_width (1.3.2)
91
+ yard (0.9.12)
92
92
 
93
93
  PLATFORMS
94
94
  ruby
@@ -98,13 +98,13 @@ DEPENDENCIES
98
98
  bundler (~> 1.16)
99
99
  codeclimate-test-reporter
100
100
  dry-validation
101
- dry-validation-matchers (~> 0.4.0)
102
101
  pry
103
102
  rake (~> 10.0)
104
103
  rspec (~> 3.0)
105
104
  rubocop
106
105
  simplecov
107
106
  typhoeus
107
+ yard (~> 0.9)
108
108
 
109
109
  BUNDLED WITH
110
110
  1.16.1
data/TODO.md CHANGED
@@ -2,5 +2,7 @@
2
2
 
3
3
  + [DONE] Create Result class to store the result after call each request
4
4
  + [DONE] Define boechat.yml expected format and adapt config classes
5
+ + [DONE] Fix call for multiple services, that don't run the requesters when using Typhoeus Hydra...
6
+ + [WIP ] Refactor version validation
5
7
  + [WIP ] Write tests for Core classes
6
- + [ ] Fix call for multiple services, that have error with Typhoeus Hydra...
8
+ + [WIP ] Document the project with YARD
data/bin/boechat ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/boechat_core'
5
+ require_relative '../lib/boechat/core/command_runner'
6
+
7
+ aliases = { 'v' => 'verify', 'c' => 'console' }
8
+
9
+ command = ARGV.first
10
+ Boechat::Core::CommandRunner.call(aliases[command] || command)
data/boechat.gemspec CHANGED
@@ -4,6 +4,7 @@ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'boechat/internal/version'
6
6
 
7
+ # rubocop:disable Metrics/BlockLength
7
8
  Gem::Specification.new do |spec|
8
9
  spec.name = 'boechat'
9
10
  spec.version = Boechat::Internal::VERSION
@@ -26,10 +27,11 @@ Gem::Specification.new do |spec|
26
27
  # rubocop:enable Style/GuardClause
27
28
 
28
29
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|bin)/}) }
29
- spec.bindir = 'exe'
30
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.bindir = 'bin'
31
+ spec.executables = ['boechat']
31
32
  spec.require_paths = ['lib']
32
33
  spec.required_ruby_version = '>= 2.5.0'
34
+ spec.metadata['yard.run'] = 'yri'
33
35
 
34
36
  # Dependencies that your gem needs at runtime
35
37
  spec.add_runtime_dependency 'dry-validation', '~> 0.11.1'
@@ -40,4 +42,6 @@ Gem::Specification.new do |spec|
40
42
  spec.add_development_dependency 'bundler', '~> 1.16'
41
43
  spec.add_development_dependency 'rake', '~> 10.0'
42
44
  spec.add_development_dependency 'rspec', '~> 3.0'
45
+ spec.add_development_dependency 'yard', '~> 0.9'
43
46
  end
47
+ # rubocop:enable Metrics/BlockLength
data/config/boechat.yml CHANGED
@@ -3,8 +3,8 @@ services:
3
3
  - name: empresas
4
4
  base_url: http://empresasservice.ad.vagastec.com.br
5
5
  status_endpoint: status
6
- http_verb: get
6
+ version: '>= 1.15.0'
7
7
  - name: processos
8
8
  base_url: http://qa-processosseletivosservice.ad.vagastec.com.br
9
9
  status_endpoint: healthcheck
10
- http_verb: get
10
+ version: '> 1.14.0'
data/lib/boechat/core.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'boechat/internal/version'
4
+ require 'boechat/core/service/verifier'
5
+ require 'pry'
4
6
 
5
7
  # :nodoc:
6
- module MyGem
8
+ module Boechat
7
9
  # :nodoc:
8
10
  module Core
9
11
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './service/verifier'
4
+
5
+ module Boechat
6
+ module Core
7
+ # Class responsible for run the commands passed to the boechat binary
8
+ class CommandRunner
9
+ def self.call(command)
10
+ if command == 'verify'
11
+ puts '-' * 80
12
+ puts 'Version Verification Result'
13
+ puts Boechat::Core::Service::Verifier.new.call.result
14
+ puts '-' * 80
15
+ else # runs help for help itself and any other not recognized command
16
+ puts "\nUSAGE:"
17
+ puts ' boechat [COMMAND]'
18
+ puts "\nCOMMANDS:"
19
+ puts ' h, help # Shows help instructions'
20
+ puts " v, verify # Verifies versions of all services contained in boachat.yml file\n"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -12,8 +12,8 @@ module Boechat
12
12
  schema do
13
13
  required('name').filled(:str?)
14
14
  required('base_url').filled(:str?)
15
+ required('version').filled(:str?)
15
16
  optional('status_endpoint').filled(:str?)
16
- optional('http_verb').filled(included_in?: %w[get post])
17
17
  end
18
18
  end
19
19
  end
@@ -1,34 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'typhoeus'
4
+
3
5
  module Boechat
4
6
  module Core
5
7
  module Service
6
- # Class to save all user request objects to execute them one at a time or all in parallel
8
+ # Class to save all user Requester objects to execute them one at a time or all in parallel
7
9
  class RequestList
8
- attr_reader :requests
10
+ attr_reader :requesters
9
11
 
10
- def initialize(requests = {})
11
- @requests = requests
12
+ def initialize(requesters = {})
13
+ @requesters = requesters
12
14
  end
13
15
 
14
- def call(request_identifier = nil)
15
- if request_identifier.nil?
16
+ # @todo Add support for multiple HTTP Clients with parallel requests
17
+ # Initially only Typhoeus HTTP client is supported for make multiple API calls in parallel.
18
+ # It will be good to support other clients, as the user wants to configure
19
+ def call(requester_identifier = nil)
20
+ if requester_identifier.nil?
16
21
  hydra = Typhoeus::Hydra.hydra
17
- requests.each_pair { |_key, request| hydra.queue(request.call) }
22
+ requesters.each_pair { |_key, requester| hydra.queue(requester.request) }
18
23
  hydra.run
19
- elsif requests.key?(request_identifier)
20
- requests[request_identifier].call
24
+ elsif requesters.key?(requester_identifier)
25
+ requesters[requester_identifier].call
21
26
  end
22
27
 
23
28
  self
24
29
  end
25
30
 
26
31
  def []=(key, requester)
27
- requests[key] = requester
32
+ requesters[key] = requester
28
33
  end
29
34
 
30
35
  def [](key)
31
- requests[key]
36
+ requesters[key]
32
37
  end
33
38
  end
34
39
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../internal/string_extensions'
4
+ require_relative 'result'
5
+ require_relative 'response_handler'
6
+ require 'typhoeus'
7
+
8
+ module Boechat
9
+ module Core
10
+ # Module to group all classes related to the Request/Response/Validation cycle
11
+ module Service
12
+ using StringExtensions
13
+
14
+ # Class responsible for make the request to one service
15
+ class Requester
16
+ attr_reader :request, :response, :result, :service_uri, :parameters, :body, :headers
17
+ BASIC_HEADER = { 'User-Agent' => 'Boechat - API Version Verifier' }.freeze
18
+
19
+ def initialize(service_uri, parameters: nil, body: nil, headers: nil)
20
+ @service_uri = service_uri
21
+ @parameters = parameters
22
+ @body = body
23
+ @headers = headers
24
+ @request = Typhoeus::Request.new(@service_uri, method: :get, params: @parameters,
25
+ body: @body, headers: http_header)
26
+ @request.on_complete do |res|
27
+ @response = res
28
+ @result = Result.new(ResponseHandler.call(res))
29
+ end
30
+ end
31
+
32
+ def call
33
+ @request.run
34
+ end
35
+
36
+ private
37
+
38
+ def http_header
39
+ return BASIC_HEADER.merge(@headers) if @headers
40
+ BASIC_HEADER
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oj'
4
+ require 'json'
5
+ require_relative '../../internal/string_extensions'
6
+
7
+ module Boechat
8
+ module Core
9
+ # Module to group all classes related to the Request/Response/Validation cycle
10
+ module Service
11
+ using StringExtensions
12
+
13
+ # Class responsible for handle the response after Request has been called
14
+ class ResponseHandler
15
+ HTTP_UNPROCESSABLE_ENTITY = 422
16
+
17
+ class << self
18
+ def call(response)
19
+ raise ArgumentError, 'Argument must respond to :body and :code' unless valid_response(response)
20
+ body = response.body
21
+
22
+ return response_error(response) if body.empty?
23
+ return response_invalid_format unless body.valid_json?
24
+ Oj.load(body, symbol_keys: true).merge(status: response.code)
25
+ end
26
+
27
+ private
28
+
29
+ def valid_response(response)
30
+ response.respond_to?(:body) && response.respond_to?(:code)
31
+ end
32
+
33
+ def response_error(response)
34
+ code = response.code
35
+
36
+ case code
37
+ when 404
38
+ Oj.load({ error: 'Not Found', status: code }.to_json, symbol_keys: true)
39
+ when 500
40
+ Oj.load({ error: 'Service Internal Error', status: code }.to_json, symbol_keys: true)
41
+ else
42
+ Oj.load({ error: 'Service Unexpected Error', status: code }.to_json, symbol_keys: true)
43
+ end
44
+ end
45
+
46
+ def response_invalid_format
47
+ Oj.load({ error: 'Invalid JSON format', status: HTTP_UNPROCESSABLE_ENTITY }.to_json, symbol_keys: true)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -14,11 +14,14 @@ module Boechat
14
14
  end
15
15
 
16
16
  def success?
17
- @parsed_response && @parsed_response[:status] < 400
17
+ @parsed_response &&
18
+ @parsed_response[:status].positive? &&
19
+ @parsed_response[:status] < 400
18
20
  end
19
21
 
20
22
  def failure?
21
- @parsed_response && @parsed_response[:status] >= 400
23
+ @parsed_response.nil? ||
24
+ (@parsed_response[:status].zero? || @parsed_response[:status] >= 400)
22
25
  end
23
26
  end
24
27
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './request'
3
+ require_relative './requester'
4
4
  require_relative './request_list'
5
+ require_relative './verifier_result'
5
6
  require_relative '../config/reader'
6
7
  require 'typhoeus'
7
8
  require 'json'
@@ -11,27 +12,37 @@ module Boechat
11
12
  module Service
12
13
  # Class responsible for call the endpoints and return all the results
13
14
  class Verifier
14
- attr_reader :config, :request_list
15
+ attr_reader :config, :request_list, :result
15
16
 
16
17
  def initialize
17
- @config = ConfigReader.new.call.config
18
+ @config = Config::Reader.new.call.config
19
+ @request_list = RequestList.new
18
20
  build_request_list
19
21
  end
20
22
 
21
23
  def call(service = nil)
22
24
  @request_list.call(service)
25
+ @result = VerifierResult.call(self)
26
+
27
+ self
23
28
  end
24
29
 
25
30
  private
26
31
 
27
32
  def build_request_list
28
- @request_list = RequestList.new
33
+ @config['services'].each_with_index do |service, index|
34
+ identifier = service['name'] || index.to_s
35
+ url = build_url(service)
29
36
 
30
- @config['services'].each do |service|
31
- key, value = service.first
32
- @request_list.requests[key] = Request.new(value['url'])
37
+ @request_list.requesters[identifier] = Requester.new(url)
33
38
  end
34
39
  end
40
+
41
+ def build_url(service)
42
+ base_url = service['base_url']
43
+ url = base_url.end_with?('/') ? base_url : "#{base_url}/"
44
+ "#{url}#{service['status_endpoint']}"
45
+ end
35
46
  end
36
47
  end
37
48
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './requester'
4
+ require_relative './request_list'
5
+ require_relative '../../internal/errors'
6
+ require 'typhoeus'
7
+ require 'json'
8
+
9
+ module Boechat
10
+ module Core
11
+ module Service
12
+ # Class responsible for call the endpoints and return all the results
13
+ class VerifierResult
14
+ include Internal
15
+
16
+ attr_reader :verifier, :output
17
+
18
+ class << self
19
+ def call(verifier)
20
+ raise BoechatError, "Verifier class expected, given #{verifier.class}." unless verifier.class == Verifier
21
+ @verifier = verifier
22
+ @output = []
23
+
24
+ @verifier.request_list.requesters.each_pair do |key, requester|
25
+ next unless requester.result
26
+ @output << { name: key,
27
+ parsed_response: requester.result.parsed_response,
28
+ valid_version: validate_response_version(key) }
29
+ end
30
+
31
+ @output
32
+ end
33
+
34
+ private
35
+
36
+ def validate_response_version(requester_identifier)
37
+ service_config = get_service_config(requester_identifier)
38
+ current_version = get_service_current_version(requester_identifier)
39
+
40
+ operator, required_version = service_config['version'].split(' ')
41
+
42
+ current_version.send(operator.to_sym, required_version)
43
+ end
44
+
45
+ def get_service_config(requester_identifier)
46
+ services = @verifier.config['services'].select do |service|
47
+ service['name'] == requester_identifier
48
+ end
49
+ services.first
50
+ end
51
+
52
+ def get_service_current_version(requester_identifier)
53
+ @verifier.request_list[requester_identifier].result.parsed_response[:tag_versao]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -3,7 +3,13 @@
3
3
  module Boechat
4
4
  module Internal
5
5
  # Custom error class
6
+ #
7
+ # @author Danilo Barion Nogueira
8
+ # @since 0.0.1
6
9
  class BoechatError < StandardError
10
+ # Constructor
11
+ #
12
+ # @param message [Object] Error message
7
13
  def initialize(message)
8
14
  super(message.to_s)
9
15
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Boechat
4
4
  module Internal
5
- VERSION = '0.0.1'
5
+ VERSION = '0.1.0-RC1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boechat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0.pre.RC1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danilo Barion Nogueira
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-02 00:00:00.000000000 Z
11
+ date: 2018-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -94,13 +94,29 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: yard
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
97
111
  description: Verify the version of external APIs that your project depends on!
98
112
  email:
99
113
  - danilo.barion@gmail.com
100
- executables: []
114
+ executables:
115
+ - boechat
101
116
  extensions: []
102
117
  extra_rdoc_files: []
103
118
  files:
119
+ - ".gitignore"
104
120
  - ".rubocop.yml"
105
121
  - ".ruby-version"
106
122
  - CHANGELOG.md
@@ -110,16 +126,20 @@ files:
110
126
  - README.md
111
127
  - Rakefile
112
128
  - TODO.md
129
+ - bin/boechat
113
130
  - boechat.gemspec
114
131
  - config/boechat.yml
115
132
  - lib/boechat/core.rb
133
+ - lib/boechat/core/command_runner.rb
116
134
  - lib/boechat/core/config/reader.rb
117
135
  - lib/boechat/core/config/schema_validator.rb
118
136
  - lib/boechat/core/config/wrapper.rb
119
- - lib/boechat/core/service/request.rb
120
137
  - lib/boechat/core/service/request_list.rb
138
+ - lib/boechat/core/service/requester.rb
139
+ - lib/boechat/core/service/response_handler.rb
121
140
  - lib/boechat/core/service/result.rb
122
141
  - lib/boechat/core/service/verifier.rb
142
+ - lib/boechat/core/service/verifier_result.rb
123
143
  - lib/boechat/internal/constants.rb
124
144
  - lib/boechat/internal/errors.rb
125
145
  - lib/boechat/internal/string_extensions.rb
@@ -130,6 +150,7 @@ licenses:
130
150
  - MIT
131
151
  metadata:
132
152
  allowed_push_host: https://rubygems.org
153
+ yard.run: yri
133
154
  post_install_message:
134
155
  rdoc_options: []
135
156
  require_paths:
@@ -141,9 +162,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
162
  version: 2.5.0
142
163
  required_rubygems_version: !ruby/object:Gem::Requirement
143
164
  requirements:
144
- - - ">="
165
+ - - ">"
145
166
  - !ruby/object:Gem::Version
146
- version: '0'
167
+ version: 1.3.1
147
168
  requirements: []
148
169
  rubyforge_project:
149
170
  rubygems_version: 2.7.3
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'oj'
4
- require_relative '../../internal/string_extensions'
5
- require_relative 'result'
6
-
7
- module Boechat
8
- module Core
9
- # Module to group all classes related to the Request/Response/Validation cycle
10
- module Service
11
- using StringExtensions
12
-
13
-
14
- # Class responsible for make the request to one service
15
- class Request
16
- attr_reader :request, :response, :result, :service_uri, :verb, :parameters, :body, :headers
17
- HTTP_UNPROCESSABLE_ENTITY = 422
18
- BASIC_HEADER = { 'User-Agent' => 'Boechat - API Version Verifier' }
19
-
20
- def initialize(service_uri, verb: :get, parameters: nil, body: nil, headers: nil)
21
- @service_uri = service_uri
22
- @verb = verb
23
- @parameters = parameters
24
- @body = body
25
- @headers = headers
26
- @request = Typhoeus::Request.new(@service_uri, method: @verb, params: @parameters,
27
- body: @body, headers: http_header)
28
- end
29
-
30
- def call
31
- handle_request
32
- end
33
-
34
- private
35
-
36
- def http_header
37
- return BASIC_HEADER.merge(@headers) if @headers
38
- BASIC_HEADER
39
- end
40
-
41
- def handle_request
42
- @request.on_complete do |res|
43
- @response = res
44
- @result = Result.new(valid_response(res))
45
- end
46
- @request.run
47
- end
48
-
49
- def valid_response(response)
50
- body = response.body
51
-
52
- return response_error(response) if body.empty?
53
- return response_invalid_format unless body.valid_json?
54
- Oj.load(body, symbol_keys: true).merge(status: response.code)
55
- end
56
-
57
- def response_error(response)
58
- code = response.code
59
-
60
- case code
61
- when 404
62
- Oj.load({ error: 'Not Found', code: code }.to_json, symbol_keys: true)
63
- when 500
64
- Oj.load({ error: 'Service Internal Error', code: code }.to_json, symbol_keys: true)
65
- else
66
- Oj.load({ error: 'Service Unexpected Error', code: code }.to_json, symbol_keys: true)
67
- end
68
- end
69
-
70
- def response_invalid_format
71
- Oj.load({ error: 'Invalid JSON format', status: HTTP_UNPROCESSABLE_ENTITY }.to_json)
72
- end
73
- end
74
- end
75
- end
76
- end