reactio 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ ---
2
+ :id: 123
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
+ :files:
43
+ - :name: "障害報告書"
44
+ :path: https://gaiax-dev.reactio.jp/data/reactio-mvp/files/incident/1/_bYMRLTxj75lcXCWN0iaAZud2CuGqFFL/Screen_Shot.png
45
+ :users:
46
+ - :id: 1
47
+ - :id: 2
@@ -0,0 +1,39 @@
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
+ - :id: 2
22
+ :name: "サイト閲覧不可2"
23
+ :manager:
24
+ :status: open
25
+ :detection: msp
26
+ :cause: over-capacity
27
+ :cause_supplement: Webサーバがアクセス過多でダウン
28
+ :point: middleware
29
+ :scale: whole
30
+ :pend_text: Webサーバの再起動を行う
31
+ :close_text: Webサーバのスケールアウトを行う
32
+ :closed_by:
33
+ :closed_at:
34
+ :pended_by:
35
+ :pended_at:
36
+ :created_by: 0
37
+ :created_at: 1430209000
38
+ :updated_by: 0
39
+ :updated_at: 1430209000
@@ -0,0 +1,18 @@
1
+ ---
2
+ :id: 33
3
+ :notification_text: "お疲れ様です。Webサーバで障害が発生しました。至急対応をお願い致します。"
4
+ :notification_call: true
5
+ :notificated_for:
6
+ :phone:
7
+ - '1'
8
+ - '3'
9
+ :email1:
10
+ - '1'
11
+ - '2'
12
+ - '3'
13
+ :email2:
14
+ - '1'
15
+ - '2'
16
+ :imkayac:
17
+ - '1'
18
+ :created_at: 1430208000
@@ -0,0 +1,19 @@
1
+ describe 'use Reactio as module' do
2
+ before do
3
+ ENV['REACTIO_API_KEY'] = 'THE_API_KEY'
4
+ ENV['REACTIO_ORGANIZATION'] = 'my-organization'
5
+ end
6
+
7
+ let(:included_class) do
8
+ Class.new.instance_eval { include Reactio }
9
+ end
10
+
11
+ let(:obj) do
12
+ included_class.new
13
+ end
14
+
15
+ it { expect(obj.reactio).to respond_to(:create_incident) }
16
+ it { expect(obj.reactio).to respond_to(:describe_incident) }
17
+ it { expect(obj.reactio).to respond_to(:list_incidents) }
18
+ it { expect(obj.reactio).to respond_to(:notify_incident) }
19
+ end
@@ -0,0 +1,40 @@
1
+ module Reactio
2
+ describe Service do
3
+ describe '.new' do
4
+ let(:api_key) { 'THE_API_KEY' }
5
+ let(:organization) { 'my-organization' }
6
+
7
+ context 'given valid options' do
8
+ subject do
9
+ described_class
10
+ .new(
11
+ api_key: api_key,
12
+ organization: organization
13
+ )
14
+ end
15
+ it { expect { subject }.to_not raise_error }
16
+ end
17
+
18
+ context 'given only api_key option' do
19
+ subject do
20
+ described_class.new(api_key: api_key)
21
+ end
22
+ it { expect { subject }.to raise_error(ArgumentError, 'organization is required') }
23
+ end
24
+
25
+ context 'given only organization option' do
26
+ subject do
27
+ described_class.new(organization: organization)
28
+ end
29
+ it { expect { subject }.to raise_error(ArgumentError, 'api_key is required') }
30
+ end
31
+
32
+ context 'given no options' do
33
+ subject do
34
+ described_class.new
35
+ end
36
+ it { expect { subject }.to raise_error(ArgumentError) }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,103 @@
1
+ require 'reactio'
2
+ require 'webmock/rspec'
3
+
4
+ Dir[File.expand_path('../support', __FILE__) + '/**/*.rb' ].each {|f| require f }
5
+
6
+ FIXTURES_ROOT = File.expand_path('../fixtures', __FILE__)
7
+
8
+ def fixture(name)
9
+ YAML.load_file("#{FIXTURES_ROOT}/#{name}.yml")
10
+ end
11
+
12
+ # This file was generated by the `rspec --init` command. Conventionally, all
13
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
14
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
15
+ # this file to always be loaded, without a need to explicitly require it in any
16
+ # files.
17
+ #
18
+ # Given that it is always loaded, you are encouraged to keep this file as
19
+ # light-weight as possible. Requiring heavyweight dependencies from this file
20
+ # will add to the boot time of your test suite on EVERY test run, even for an
21
+ # individual file that may not need all of that loaded. Instead, consider making
22
+ # a separate helper file that requires the additional dependencies and performs
23
+ # the additional setup, and require it from the spec files that actually need
24
+ # it.
25
+ #
26
+ # The `.rspec` file also contains a few flags that are not defaults but that
27
+ # users commonly want.
28
+ #
29
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
30
+ RSpec.configure do |config|
31
+ config.include RequestStubHelper
32
+ # rspec-expectations config goes here. You can use an alternate
33
+ # assertion/expectation library such as wrong or the stdlib/minitest
34
+ # assertions if you prefer.
35
+ config.expect_with :rspec do |expectations|
36
+ # This option will default to `true` in RSpec 4. It makes the `description`
37
+ # and `failure_message` of custom matchers include text for helper methods
38
+ # defined using `chain`, e.g.:
39
+ # be_bigger_than(2).and_smaller_than(4).description
40
+ # # => "be bigger than 2 and smaller than 4"
41
+ # ...rather than:
42
+ # # => "be bigger than 2"
43
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
44
+ end
45
+
46
+ # rspec-mocks config goes here. You can use an alternate test double
47
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
48
+ config.mock_with :rspec do |mocks|
49
+ # Prevents you from mocking or stubbing a method that does not exist on
50
+ # a real object. This is generally recommended, and will default to
51
+ # `true` in RSpec 4.
52
+ mocks.verify_partial_doubles = true
53
+ end
54
+
55
+ # The settings below are suggested to provide a good initial experience
56
+ # with RSpec, but feel free to customize to your heart's content.
57
+ =begin
58
+ # These two settings work together to allow you to limit a spec run
59
+ # to individual examples or groups you care about by tagging them with
60
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
61
+ # get run.
62
+ config.filter_run :focus
63
+ config.run_all_when_everything_filtered = true
64
+
65
+ # Limits the available syntax to the non-monkey patched syntax that is
66
+ # recommended. For more details, see:
67
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
68
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
70
+ config.disable_monkey_patching!
71
+
72
+ # This setting enables warnings. It's recommended, but in some cases may
73
+ # be too noisy due to issues in dependencies.
74
+ config.warnings = true
75
+
76
+ # Many RSpec users commonly either run the entire suite or an individual
77
+ # file, and it's useful to allow more verbose output when running an
78
+ # individual spec file.
79
+ if config.files_to_run.one?
80
+ # Use the documentation formatter for detailed output,
81
+ # unless a formatter has already been configured
82
+ # (e.g. via a command-line flag).
83
+ config.default_formatter = 'doc'
84
+ end
85
+
86
+ # Print the 10 slowest examples and example groups at the
87
+ # end of the spec run, to help surface which specs are running
88
+ # particularly slow.
89
+ config.profile_examples = 10
90
+
91
+ # Run specs in random order to surface order dependencies. If you find an
92
+ # order dependency and want to debug it, you can fix the order by providing
93
+ # the seed, which is printed after each run.
94
+ # --seed 1234
95
+ config.order = :random
96
+
97
+ # Seed global randomization in this process using the `--seed` CLI option.
98
+ # Setting this allows you to use `--seed` to deterministically reproduce
99
+ # test failures related to randomization by passing the same `--seed` value
100
+ # as the one that triggered the failure.
101
+ Kernel.srand config.seed
102
+ =end
103
+ end
@@ -0,0 +1,5 @@
1
+ shared_context 'default_service_context' do
2
+ let(:service) { Reactio::Service.new(api_key: api_key, organization: organization) }
3
+ let(:api_key) { 'api_key_for_organization' }
4
+ let(:organization) { 'your-organization' }
5
+ end
@@ -0,0 +1,25 @@
1
+ require 'json'
2
+
3
+ module RequestStubHelper
4
+ MIME_TYPE = 'application/json'.freeze
5
+
6
+ def stub_api_request(organization, api_key, spec)
7
+ params = {}
8
+ params[:headers] = build_headers(api_key)
9
+ params[:body] = spec[:body] if spec.key?(:body)
10
+ params[:query] = spec[:query] if spec.key?(:query)
11
+
12
+ stub_request(
13
+ spec[:method],
14
+ "https://#{organization}.reactio.jp#{spec[:path]}"
15
+ ).with(params)
16
+ end
17
+
18
+ def build_headers(api_key)
19
+ {
20
+ 'Accept' => MIME_TYPE,
21
+ 'Content-Type' => MIME_TYPE,
22
+ 'X-Api-Key' => api_key
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,254 @@
1
+ describe 'create incident' do
2
+ include_context 'default_service_context'
3
+
4
+ subject do
5
+ service.create_incident(name, options)
6
+ end
7
+
8
+ let(:name) { 'サイト閲覧不可' }
9
+
10
+ before { stub }
11
+
12
+ let(:stub) do
13
+ stub_api_request(
14
+ organization, api_key,
15
+ method: :post, path: '/api/v1/incidents',
16
+ body: { name: name }.merge(expected_options).to_json
17
+ ).to_return(
18
+ status: 201,
19
+ body: incident.to_json
20
+ )
21
+ end
22
+
23
+ let(:incident) { fixture('created_incident') }
24
+
25
+ context 'without options' do
26
+ subject { service.create_incident(name) }
27
+ let(:expected_options) { {} }
28
+ it { is_expected.to eq(incident) }
29
+ end
30
+
31
+ context 'with status option' do
32
+ let(:options) { { status: status } }
33
+ let(:expected_options) { { status: status } }
34
+
35
+ context 'given :open as status' do
36
+ let(:status) { 'open' }
37
+ it { is_expected.to eq(incident) }
38
+ end
39
+
40
+ context 'given :pend as status' do
41
+ let(:status) { 'pend' }
42
+ it { is_expected.to eq(incident) }
43
+ end
44
+
45
+ context 'given :close as status' do
46
+ let(:status) { 'close' }
47
+ it { is_expected.to eq(incident) }
48
+ end
49
+ end
50
+
51
+ context 'with detection option' do
52
+ let(:options) { { detection: detection } }
53
+
54
+ context 'given :msp as detection' do
55
+ let(:detection) { 'msp' }
56
+ let(:expected_options) { { detection: 'msp' } }
57
+ it { is_expected.to eq(incident) }
58
+ end
59
+
60
+ context 'given :system as detection' do
61
+ let(:detection) { 'system' }
62
+ let(:expected_options) { { detection: 'system' } }
63
+ it { is_expected.to eq(incident) }
64
+ end
65
+
66
+ context 'given :client as detection' do
67
+ let(:detection) { 'client' }
68
+ let(:expected_options) { { detection: 'client' } }
69
+ it { is_expected.to eq(incident) }
70
+ end
71
+
72
+ context 'given :internal as detection' do
73
+ let(:detection) { 'internal' }
74
+ let(:expected_options) { { detection: 'internal' } }
75
+ it { is_expected.to eq(incident) }
76
+ end
77
+
78
+ context 'given nil as detection' do
79
+ let(:detection) { nil }
80
+ let(:expected_options) { { detection: 'null' } }
81
+ it { is_expected.to eq(incident) }
82
+ end
83
+ end
84
+
85
+ context 'with cause option' do
86
+ let(:options) { { cause: cause } }
87
+
88
+ context 'given over-capacity as cause' do
89
+ let(:cause) { 'over-capacity' }
90
+ let(:expected_options) { { cause: 'over-capacity' } }
91
+ it { is_expected.to eq(incident) }
92
+ end
93
+
94
+ context 'given bug as cause' do
95
+ let(:cause) { 'bug' }
96
+ let(:expected_options) { { cause: 'bug' } }
97
+ it { is_expected.to eq(incident) }
98
+ end
99
+
100
+ context 'given operation-error as cause' do
101
+ let(:cause) { 'operation-error' }
102
+ let(:expected_options) { { cause: 'operation-error' } }
103
+ it { is_expected.to eq(incident) }
104
+ end
105
+
106
+ context 'given external-factor as cause' do
107
+ let(:cause) { 'external-factor' }
108
+ let(:expected_options) { { cause: 'external-factor' } }
109
+ it { is_expected.to eq(incident) }
110
+ end
111
+
112
+ context 'given degradation as cause' do
113
+ let(:cause) { 'degradation' }
114
+ let(:expected_options) { { cause: 'degradation' } }
115
+ it { is_expected.to eq(incident) }
116
+ end
117
+
118
+ context 'given unknown as cause' do
119
+ let(:cause) { 'unknown' }
120
+ let(:expected_options) { { cause: 'unknown' } }
121
+ it { is_expected.to eq(incident) }
122
+ end
123
+
124
+ context 'given nil as cause' do
125
+ let(:cause) { nil }
126
+ let(:expected_options) { { cause: 'null' } }
127
+ it { is_expected.to eq(incident) }
128
+ end
129
+ end
130
+
131
+ context 'with cause_supplement option' do
132
+ let(:options) { { cause_supplement: cause_supplement } }
133
+ let(:expected_options) { { cause_supplement: cause_supplement } }
134
+ let(:cause_supplement) { 'Webサーバがアクセス過多でダウン' }
135
+ it { is_expected.to eq(incident) }
136
+ end
137
+
138
+ context 'with point option' do
139
+ let(:options) { { point: point } }
140
+
141
+ context 'given network as point' do
142
+ let(:point) { 'network' }
143
+ let(:expected_options) { { point: 'network' } }
144
+ it { is_expected.to eq(incident) }
145
+ end
146
+
147
+ context 'given shared-hardware as point' do
148
+ let(:point) { 'shared-hardware' }
149
+ let(:expected_options) { { point: 'shared-hardware' } }
150
+ it { is_expected.to eq(incident) }
151
+ end
152
+
153
+ context 'given hardware as point' do
154
+ let(:point) { 'hardware' }
155
+ let(:expected_options) { { point: 'hardware' } }
156
+ it { is_expected.to eq(incident) }
157
+ end
158
+
159
+ context 'given os as point' do
160
+ let(:point) { 'os' }
161
+ let(:expected_options) { { point: 'os' } }
162
+ it { is_expected.to eq(incident) }
163
+ end
164
+
165
+ context 'given middleware as point' do
166
+ let(:point) { 'middleware' }
167
+ let(:expected_options) { { point: 'middleware' } }
168
+ it { is_expected.to eq(incident) }
169
+ end
170
+
171
+ context 'given application as point' do
172
+ let(:point) { 'application' }
173
+ let(:expected_options) { { point: 'application' } }
174
+ it { is_expected.to eq(incident) }
175
+ end
176
+
177
+ context 'given nil as point' do
178
+ let(:point) { nil }
179
+ let(:expected_options) { { point: 'null' } }
180
+ it { is_expected.to eq(incident) }
181
+ end
182
+ end
183
+
184
+ context 'with scale option' do
185
+ let(:options) { { scale: scale } }
186
+
187
+ context 'given cross as scale' do
188
+ let(:scale) { 'cross' }
189
+ let(:expected_options) { { scale: 'cross' } }
190
+ it { is_expected.to eq(incident) }
191
+ end
192
+
193
+ context 'given whole as scale' do
194
+ let(:scale) { 'whole' }
195
+ let(:expected_options) { { scale: 'whole' } }
196
+ it { is_expected.to eq(incident) }
197
+ end
198
+
199
+ context 'given point as scale' do
200
+ let(:scale) { 'point' }
201
+ let(:expected_options) { { scale: 'point' } }
202
+ it { is_expected.to eq(incident) }
203
+ end
204
+
205
+ context 'given nil as scale' do
206
+ let(:scale) { nil }
207
+ let(:expected_options) { { scale: 'null' } }
208
+ it { is_expected.to eq(incident) }
209
+ end
210
+ end
211
+
212
+ context 'with pend_text option' do
213
+ let(:options) { { pend_text: pend_text } }
214
+ let(:expected_options) { { pend_text: pend_text } }
215
+ let(:pend_text) { 'Webサーバの再起動を行う' }
216
+ it { is_expected.to eq(incident) }
217
+ end
218
+
219
+ context 'with close_text option' do
220
+ let(:options) { { close_text: close_text } }
221
+ let(:expected_options) { { close_text: close_text } }
222
+ let(:close_text) { 'Webサーバのスケールアウトを行う' }
223
+ it { is_expected.to eq(incident) }
224
+ end
225
+
226
+ context 'with topics option' do
227
+ let(:options) { { topics: topics } }
228
+ let(:expected_options) { { topics: topics } }
229
+ let(:topics) { %w(原因調査 復旧作業) }
230
+ it { is_expected.to eq(incident) }
231
+ end
232
+
233
+ context 'with notification_text option' do
234
+ let(:options) { { notification_text: notification_text } }
235
+ let(:expected_options) { { notification_text: notification_text } }
236
+ let(:notification_text) { '至急対応をお願いします。' }
237
+ it { is_expected.to eq(incident) }
238
+ end
239
+
240
+ context 'with notification_call option' do
241
+ let(:options) { { notification_call: notification_call } }
242
+ let(:expected_options) { { notification_call: notification_call } }
243
+
244
+ context 'given true as notification_call' do
245
+ let(:notification_call) { true }
246
+ it { is_expected.to eq(incident) }
247
+ end
248
+
249
+ context 'given false as notification_call' do
250
+ let(:notification_call) { false }
251
+ it { is_expected.to eq(incident) }
252
+ end
253
+ end
254
+ end