reactio 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +118 -0
- data/Rakefile +2 -0
- data/lib/reactio.rb +29 -0
- data/lib/reactio/api_client.rb +53 -0
- data/lib/reactio/api_endpoint.rb +23 -0
- data/lib/reactio/errors.rb +5 -0
- data/lib/reactio/faraday_engine.rb +43 -0
- data/lib/reactio/service.rb +46 -0
- data/lib/reactio/utils.rb +10 -0
- data/lib/reactio/version.rb +3 -0
- data/reactio.gemspec +27 -0
- data/spec/fixtures/created_incident.yml +59 -0
- data/spec/fixtures/incident.yml +47 -0
- data/spec/fixtures/incident_list.yml +39 -0
- data/spec/fixtures/notification.yml +18 -0
- data/spec/reactio_spec.rb +19 -0
- data/spec/service_spec.rb +40 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/support/default_client_context.rb +5 -0
- data/spec/support/request_stub_helper.rb +25 -0
- data/spec/v1/create_incident_spec.rb +254 -0
- data/spec/v1/describe_incident_spec.rb +23 -0
- data/spec/v1/error_handling_spec.rb +62 -0
- data/spec/v1/list_incidents_spec.rb +76 -0
- data/spec/v1/notify_incident_spec.rb +52 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 36606269241ac620fd46cec36ca3cf045e3b8908
|
4
|
+
data.tar.gz: 85c450f2de769ae85546cb9031cedd4671cb90a8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fe2eadf9a63c611c44cf8bd41665f20b706684f1c69e2d84ffacd777556d189f247c4b9c90f292f40c7580ac76676a94626756c6f32382df2b9236a8898c6855
|
7
|
+
data.tar.gz: 8e3e02366a1851008c23b279145b2b47c3fadabe19a4d3aa615007fc11756f295609da0645d8232e555005277f9ffa74d70caa5b7650b09fdf354cde2a103ef8
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Hajime Sueyoshi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# Reactio
|
2
|
+
|
3
|
+
Reactio API Client for ruby
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'reactio'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install reactio
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### include Reactio
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'reactio'
|
27
|
+
include Reactio
|
28
|
+
|
29
|
+
reactio.create_incident('An Incident')
|
30
|
+
```
|
31
|
+
|
32
|
+
And run:
|
33
|
+
|
34
|
+
$ REACTIO_API_KEY='YOUR_API_KEY' REACTIO_ORGANIZATION='YOUR_ORGANIZATION' bundle exec ruby create_incident.rb
|
35
|
+
|
36
|
+
### Or instantiate Reactio::Service
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
require 'reactio'
|
40
|
+
|
41
|
+
reactio = Reactio::Service.new(
|
42
|
+
api_key: 'YOUR_API_KEY',
|
43
|
+
organization: 'YOUR_ORGANIZATION'
|
44
|
+
)
|
45
|
+
reactio.create_incident('An Incident')
|
46
|
+
```
|
47
|
+
|
48
|
+
### Reactio incidents
|
49
|
+
|
50
|
+
- インシデント作成(およびトピック登録)
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
require 'reactio'
|
54
|
+
include Reactio
|
55
|
+
|
56
|
+
reactio.create_incident(
|
57
|
+
'サイト閲覧不可',
|
58
|
+
status: 'open',
|
59
|
+
detection: 'internal',
|
60
|
+
cause: 'over-capacity',
|
61
|
+
cause_supplement: 'Webサーバがアクセス過多でダウン',
|
62
|
+
point: 'application',
|
63
|
+
scale: 'point',
|
64
|
+
pend_text: 'Webサーバの再起動を行う',
|
65
|
+
topics: %w(原因調査 復旧作業),
|
66
|
+
notification_text: '至急対応をお願いします',
|
67
|
+
notification_call: false
|
68
|
+
)
|
69
|
+
```
|
70
|
+
|
71
|
+
- 一斉通知
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
require 'reactio'
|
75
|
+
include Reactio
|
76
|
+
|
77
|
+
reactio.notify_incident(
|
78
|
+
123,
|
79
|
+
notification_text: '至急対応をお願いします',
|
80
|
+
notification_call: true
|
81
|
+
)
|
82
|
+
```
|
83
|
+
|
84
|
+
- インシデント一覧取得
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
require 'reactio'
|
88
|
+
include Reactio
|
89
|
+
|
90
|
+
list = reactio.list_incidents(
|
91
|
+
from: Time.now - (60 * 60 * 24 * 7),
|
92
|
+
to: Time.now,
|
93
|
+
status: 'pend',
|
94
|
+
page: 1,
|
95
|
+
per_page: 50
|
96
|
+
)
|
97
|
+
|
98
|
+
p list.first
|
99
|
+
#=> {:id=>1, :name=>"サイト閲覧不可", :manager=>nil, :status=>"pend", :detection=>"msp", :cause=>"over-capacity", :cause_supplement=>"Webサーバがアクセス過多でダウン", :point=>"middleware", :scale=>"whole", :pend_text=>"Webサーバの再起動を行う", :close_text=>"Webサーバのスケールアウトを行う", :closed_by=>nil, :closed_at=>nil, :pended_by=>nil, :pended_at=>nil, :created_by=>0, :created_at=>1430208000, :updated_by=>0, :updated_at=>1430208000}
|
100
|
+
```
|
101
|
+
|
102
|
+
- インシデント取得
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
require 'reactio'
|
106
|
+
include Reactio
|
107
|
+
|
108
|
+
p reactio.describe_incident(123)
|
109
|
+
#=> {:id=>123, :name=>"サイト閲覧不可", :manager=>nil, :status=>"open", :detection=>"msp", :cause=>"over-capacity", :cause_supplement=>"Webサーバがアクセス過多でダウン", :point=>"middleware", :scale=>"whole", :pend_text=>"Webサーバの再起動を行う", :close_text=>"Webサーバのスケールアウトを行う", :closed_by=>nil, :closed_at=>nil, :pended_by=>nil, :pended_at=>nil, :created_by=>0, :created_at=>1430208000, :updated_by=>0, :updated_at=>1430208000, :topics=>[{:id=>1, :name=>"原因調査", :status=>"open", :color=>"#5661aa", :closed_by=>nil, :closed_at=>nil, :created_by=>0, :created_at=>1430208000, :updated_by=>0, :updated_at=>1430208000}, {:id=>2, :name=>"復旧作業", :status=>"open", :color=>"#077f40", :closed_by=>nil, :closed_at=>nil, :created_by=>0, :created_at=>1430208000, :updated_by=>0, :updated_at=>1430208000}], :files=>[{:name=>"障害報告書", :path=>"https://demo.reactio.jp/data/reactio-mvp/files/incident/1/_bYMRLTxj75lcXCWN0iaAZud2CuGqFFL/Screen_Shot.png"}], :users=>[{:id=>1}, {:id=>2}]}
|
110
|
+
```
|
111
|
+
|
112
|
+
## Contributing
|
113
|
+
|
114
|
+
1. Fork it ( https://github.com/[my-github-username]/reactio/fork )
|
115
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
116
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
117
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
118
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/reactio.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'reactio/version'
|
2
|
+
require 'reactio/errors'
|
3
|
+
require 'reactio/utils'
|
4
|
+
require 'reactio/service'
|
5
|
+
|
6
|
+
module Reactio
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
include InstanceMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
|
16
|
+
def reactio
|
17
|
+
@reactio ||= create_service
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def create_service
|
23
|
+
Service.new(
|
24
|
+
api_key: ENV['REACTIO_API_KEY'],
|
25
|
+
organization: ENV['REACTIO_ORGANIZATION']
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'reactio/api_endpoint'
|
3
|
+
require 'reactio/faraday_engine'
|
4
|
+
|
5
|
+
module Reactio
|
6
|
+
class APIClient
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def build(api_key, organization)
|
11
|
+
raise ArgumentError, 'api_key is required' unless api_key
|
12
|
+
raise ArgumentError, 'organization is required' unless organization
|
13
|
+
http_client = build_http_client(
|
14
|
+
api_key,
|
15
|
+
APIEndpoint.new(organization)
|
16
|
+
)
|
17
|
+
new(http_client)
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_http_client(api_key, api_endpoint)
|
21
|
+
Faraday.new(url: api_endpoint.base_url) do |faraday|
|
22
|
+
faraday.use :reactio, api_key
|
23
|
+
faraday.request :url_encoded
|
24
|
+
faraday.adapter Faraday.default_adapter
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(http_client)
|
30
|
+
@http = http_client
|
31
|
+
end
|
32
|
+
|
33
|
+
def request(method, path, env = {})
|
34
|
+
response = @http.send(method, path, env[:body])
|
35
|
+
handle_api_response(response)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def handle_api_response(res)
|
41
|
+
case res.status
|
42
|
+
when 200..299
|
43
|
+
res.body
|
44
|
+
when 401
|
45
|
+
raise Reactio::AuthenticationError, res.body.inspect
|
46
|
+
when 400..499
|
47
|
+
raise Reactio::BadRequest, res.body.inspect
|
48
|
+
when 500..599
|
49
|
+
raise Reactio::ServerError, res.body.inspect
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Reactio
|
4
|
+
class APIEndpoint
|
5
|
+
DOMAIN = 'reactio.jp'.freeze
|
6
|
+
|
7
|
+
attr_reader :organization
|
8
|
+
|
9
|
+
def initialize(organization)
|
10
|
+
@organization = organization
|
11
|
+
@base_url = URI::HTTPS.build(host: "#{organization}.#{DOMAIN}")
|
12
|
+
end
|
13
|
+
|
14
|
+
def base_url
|
15
|
+
@base_url.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
other.instance_of?(self.class) &&
|
20
|
+
self.organization == other.organization
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Reactio
|
5
|
+
class FaradayEngine < Faraday::Middleware
|
6
|
+
USER_AGENT = "Reactio ruby v#{VERSION}".freeze
|
7
|
+
MIME_TYPE = 'application/json'.freeze
|
8
|
+
|
9
|
+
def initialize(app, api_key)
|
10
|
+
super(app)
|
11
|
+
@api_key = api_key
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(request_env)
|
15
|
+
set_request_header(request_env)
|
16
|
+
encode_body(request_env)
|
17
|
+
@app.call(request_env).on_complete do |response_env|
|
18
|
+
decode_body(response_env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def set_request_header(env)
|
25
|
+
env[:request_headers].merge!(
|
26
|
+
'Accept' => MIME_TYPE,
|
27
|
+
'Content-Type' => MIME_TYPE,
|
28
|
+
'X-Api-Key' => @api_key,
|
29
|
+
'User-Agent' => USER_AGENT
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def encode_body(env)
|
34
|
+
env[:body] = JSON.dump(env[:body])
|
35
|
+
end
|
36
|
+
|
37
|
+
def decode_body(env)
|
38
|
+
env[:body] = JSON.parse(env[:body], symbolize_names: true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Faraday::Middleware.register_middleware reactio: Reactio::FaradayEngine
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'reactio/api_client'
|
2
|
+
|
3
|
+
module Reactio
|
4
|
+
class Service
|
5
|
+
include Utils
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@api = APIClient.build(
|
9
|
+
options[:api_key],
|
10
|
+
options[:organization]
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_incident(name, options = {})
|
15
|
+
payload = { name: name }.tap do |me|
|
16
|
+
me[:detection] = to_option_string(options.delete(:detection)) if options.key?(:detection)
|
17
|
+
me[:cause] = to_option_string(options.delete(:cause)) if options.key?(:cause)
|
18
|
+
me[:point] = to_option_string(options.delete(:point)) if options.key?(:point)
|
19
|
+
me[:scale] = to_option_string(options.delete(:scale)) if options.key?(:scale)
|
20
|
+
end
|
21
|
+
.merge!(options)
|
22
|
+
@api.request(:post, "/api/v1/incidents", body: payload)
|
23
|
+
end
|
24
|
+
|
25
|
+
def describe_incident(incident_id)
|
26
|
+
@api.request(:get, "/api/v1/incidents/#{incident_id}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def list_incidents(options = {})
|
30
|
+
payload = {}.tap do |me|
|
31
|
+
me[:from] = options.delete(:from).to_i if options[:from]
|
32
|
+
me[:to] = options.delete(:to).to_i if options[:to]
|
33
|
+
me[:status] = options.delete(:status).to_s if options[:status]
|
34
|
+
end
|
35
|
+
.merge!(options)
|
36
|
+
@api.request(:get, "/api/v1/incidents", body: payload)
|
37
|
+
end
|
38
|
+
|
39
|
+
def notify_incident(incident_id, options = {})
|
40
|
+
@api.request(
|
41
|
+
:post, "/api/v1/notifications",
|
42
|
+
body: { incident_id: incident_id }.merge(options)
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/reactio.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'reactio/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "reactio"
|
8
|
+
spec.version = Reactio::VERSION
|
9
|
+
spec.authors = ["Hajime Sueyoshi"]
|
10
|
+
spec.email = ["hajime.sueyoshi@gaiax.com"]
|
11
|
+
spec.summary = %q{Reactio API Client}
|
12
|
+
spec.description = %q{The official Reactio API Client for ruby.}
|
13
|
+
spec.homepage = "https://reactio.jp/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "faraday"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "webmock"
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
---
|
2
|
+
:id: 1
|
3
|
+
:name: "サイト閲覧不可"
|
4
|
+
:manager:
|
5
|
+
:status: open
|
6
|
+
:detection: msp
|
7
|
+
:cause: over-capacity
|
8
|
+
:cause_supplement: Webサーバがアクセス過多でダウン
|
9
|
+
:point: middleware
|
10
|
+
:scale: whole
|
11
|
+
:pend_text: Webサーバの再起動を行う
|
12
|
+
:close_text: Webサーバのスケールアウトを行う
|
13
|
+
:closed_by:
|
14
|
+
:closed_at:
|
15
|
+
:pended_by:
|
16
|
+
:pended_at:
|
17
|
+
:created_by: 0
|
18
|
+
:created_at: 1430208000
|
19
|
+
:updated_by: 0
|
20
|
+
:updated_at: 1430208000
|
21
|
+
:topics:
|
22
|
+
- :id: 1
|
23
|
+
:name: "原因調査"
|
24
|
+
:status: open
|
25
|
+
:color: "#5661aa"
|
26
|
+
:closed_by:
|
27
|
+
:closed_at:
|
28
|
+
:created_by: 0
|
29
|
+
:created_at: 1430208000
|
30
|
+
:updated_by: 0
|
31
|
+
:updated_at: 1430208000
|
32
|
+
- :id: 2
|
33
|
+
:name: "復旧作業"
|
34
|
+
:status: open
|
35
|
+
:color: "#077f40"
|
36
|
+
:closed_by:
|
37
|
+
:closed_at:
|
38
|
+
:created_by: 0
|
39
|
+
:created_at: 1430208000
|
40
|
+
:updated_by: 0
|
41
|
+
:updated_at: 1430208000
|
42
|
+
:notifications:
|
43
|
+
:id: 1
|
44
|
+
:notification_text: "お疲れ様です。Webサーバで障害が発生しました。至急対応をお願い致します。"
|
45
|
+
:notification_call: true
|
46
|
+
:notificated_for:
|
47
|
+
:phone:
|
48
|
+
- '1'
|
49
|
+
- '3'
|
50
|
+
:email1:
|
51
|
+
- '1'
|
52
|
+
- '2'
|
53
|
+
- '3'
|
54
|
+
:email2:
|
55
|
+
- '1'
|
56
|
+
- '2'
|
57
|
+
:imkayac:
|
58
|
+
- '1'
|
59
|
+
:created_at: 1430208000
|