reactio 1.0.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,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