status_page_ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +25 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +61 -0
- data/README.md +53 -0
- data/bin/status-page +6 -0
- data/lib/status_page_ruby.rb +20 -0
- data/lib/status_page_ruby/pages/base.rb +52 -0
- data/lib/status_page_ruby/pages/bitbucket.rb +14 -0
- data/lib/status_page_ruby/pages/cloudflare.rb +29 -0
- data/lib/status_page_ruby/pages/github.rb +19 -0
- data/lib/status_page_ruby/pages/rubygems.rb +14 -0
- data/lib/status_page_ruby/repositories/status.rb +40 -0
- data/lib/status_page_ruby/services/backup_data.rb +15 -0
- data/lib/status_page_ruby/services/build_history_table.rb +32 -0
- data/lib/status_page_ruby/services/build_log_table.rb +14 -0
- data/lib/status_page_ruby/services/build_stats_table.rb +79 -0
- data/lib/status_page_ruby/services/pull_statuses.rb +44 -0
- data/lib/status_page_ruby/services/restore_data.rb +15 -0
- data/lib/status_page_ruby/status.rb +36 -0
- data/lib/status_page_ruby/storage.rb +55 -0
- data/lib/status_page_ruby/version.rb +3 -0
- data/lib/status_page_ruby_cli.rb +76 -0
- data/spec/lib/status_page_ruby/pages/bitbucket_spec.rb +39 -0
- data/spec/lib/status_page_ruby/pages/cloudflare_spec.rb +64 -0
- data/spec/lib/status_page_ruby/pages/github_spec.rb +57 -0
- data/spec/lib/status_page_ruby/pages/rubygems_spec.rb +39 -0
- data/spec/lib/status_page_ruby/repositories/status_spec.rb +124 -0
- data/spec/lib/status_page_ruby/services/backup_data_spec.rb +13 -0
- data/spec/lib/status_page_ruby/services/build_history_table_spec.rb +71 -0
- data/spec/lib/status_page_ruby/services/build_log_table_spec.rb +43 -0
- data/spec/lib/status_page_ruby/services/build_stats_table_spec.rb +72 -0
- data/spec/lib/status_page_ruby/services/pull_statuses_spec.rb +30 -0
- data/spec/lib/status_page_ruby/services/restore_data_spec.rb +13 -0
- data/spec/lib/status_page_ruby/status_spec.rb +65 -0
- data/spec/lib/status_page_ruby/storage_spec.rb +134 -0
- data/spec/spec_helper.rb +15 -0
- data/status_page_ruby.gemspec +22 -0
- metadata +139 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Pages::Rubygems do
|
4
|
+
let(:html) { "<html><body><div class='page-status'><div class='status'>#{status}</div></div></body></html>" }
|
5
|
+
|
6
|
+
before { allow(OpenURI).to receive(:open_uri).with('https://status.rubygems.org/') { html } }
|
7
|
+
|
8
|
+
describe '#status' do
|
9
|
+
subject { described_class.open.status }
|
10
|
+
|
11
|
+
context 'when success status' do
|
12
|
+
let(:status) { 'All Systems Operational' }
|
13
|
+
|
14
|
+
it { is_expected.to eq('All Systems Operational') }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when not success status' do
|
18
|
+
let(:status) { 'All is Failed' }
|
19
|
+
|
20
|
+
it { is_expected.to eq('All is Failed') }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#success?' do
|
25
|
+
subject { described_class.open.success? }
|
26
|
+
|
27
|
+
context 'when success status' do
|
28
|
+
let(:status) { 'All Systems Operational' }
|
29
|
+
|
30
|
+
it { is_expected.to be_truthy }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when not success status' do
|
34
|
+
let(:status) { 'All is Failed' }
|
35
|
+
|
36
|
+
it { is_expected.to be_falsey }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Repositories::Status do
|
4
|
+
let(:storage) { double }
|
5
|
+
let(:repository) { described_class.new(storage) }
|
6
|
+
|
7
|
+
describe '#exist?' do
|
8
|
+
subject { repository.exist?(status) }
|
9
|
+
let(:status) { double(record: double) }
|
10
|
+
|
11
|
+
before { allow(storage).to receive(:include?).with(status.record) { is_include } }
|
12
|
+
|
13
|
+
context 'when storage includes status record' do
|
14
|
+
let(:is_include) { true }
|
15
|
+
it { is_expected.to be_truthy }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when storage does not include status record' do
|
19
|
+
let(:is_include) { false }
|
20
|
+
it { is_expected.to be_falsey }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#where' do
|
25
|
+
subject { repository.where(service: 'a') }
|
26
|
+
|
27
|
+
context 'when storage is not empty' do
|
28
|
+
context 'when service exists' do
|
29
|
+
before { allow(storage).to receive(:read) { [%w[a b c]] } }
|
30
|
+
|
31
|
+
it 'builds statuses' do
|
32
|
+
expect(StatusPageRuby::Status).to receive(:new).with('a', 'b', 'c')
|
33
|
+
subject
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when service does not exist' do
|
38
|
+
before { allow(storage).to receive(:read) { [%w[x x x]] } }
|
39
|
+
|
40
|
+
it 'builds statuses' do
|
41
|
+
expect(StatusPageRuby::Status).not_to receive(:new)
|
42
|
+
subject
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when storage is empty' do
|
48
|
+
before { allow(storage).to receive(:read) { [] } }
|
49
|
+
|
50
|
+
it 'does not build statuses' do
|
51
|
+
expect(StatusPageRuby::Status).not_to receive(:new)
|
52
|
+
subject
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#all' do
|
58
|
+
subject { repository.all }
|
59
|
+
|
60
|
+
context 'when storage is not empty' do
|
61
|
+
before { allow(storage).to receive(:read) { [%w[a b c]] } }
|
62
|
+
|
63
|
+
it 'builds statuses' do
|
64
|
+
expect(StatusPageRuby::Status).to receive(:new).with('a', 'b', 'c')
|
65
|
+
subject
|
66
|
+
end
|
67
|
+
end
|
68
|
+
context 'when storage is empty' do
|
69
|
+
before { allow(storage).to receive(:read) { [] } }
|
70
|
+
|
71
|
+
it 'does not build statuses' do
|
72
|
+
expect(StatusPageRuby::Status).not_to receive(:new)
|
73
|
+
subject
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#create' do
|
79
|
+
subject { repository.create(status) }
|
80
|
+
let(:status) { double(record: double) }
|
81
|
+
|
82
|
+
before { allow(repository).to receive(:exist?) { status_exists } }
|
83
|
+
|
84
|
+
context 'when status does not exist' do
|
85
|
+
let(:status_exists) { false }
|
86
|
+
|
87
|
+
it 'triggers write on storage' do
|
88
|
+
expect(storage).to receive(:write).with(status.record).once
|
89
|
+
subject
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'with status exists' do
|
94
|
+
let(:status_exists) { true }
|
95
|
+
|
96
|
+
it 'does not trigger write on storage' do
|
97
|
+
expect(storage).not_to receive(:write)
|
98
|
+
subject
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#create_batch' do
|
104
|
+
subject { repository.create_batch(statuses) }
|
105
|
+
|
106
|
+
context 'with statuses' do
|
107
|
+
let(:statuses) { [double(record: double)] }
|
108
|
+
|
109
|
+
it 'triggers merge on storage' do
|
110
|
+
expect(storage).to receive(:merge).with(statuses.map(&:record)).once
|
111
|
+
subject
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'with empty statuses' do
|
116
|
+
let(:statuses) { [] }
|
117
|
+
|
118
|
+
it 'does not trigger merge on storage' do
|
119
|
+
expect(storage).not_to receive(:merge)
|
120
|
+
subject
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BackupData do
|
4
|
+
let(:storage) { double }
|
5
|
+
let(:service) { described_class.new(storage) }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
it 'triggers copy on storage' do
|
9
|
+
expect(storage).to receive(:copy).with('test_path').once
|
10
|
+
service.call('test_path')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BuildHistoryTable do
|
4
|
+
let(:data_file_path) { Tempfile.new('data_file_path').path }
|
5
|
+
let(:service) do
|
6
|
+
described_class.new(
|
7
|
+
StatusPageRuby::Repositories::Status.new(
|
8
|
+
StatusPageRuby::Storage.new(data_file_path)
|
9
|
+
)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#call' do
|
14
|
+
before do
|
15
|
+
File.write(data_file_path, <<-CSV.delete(' '))
|
16
|
+
test1,up,Success,1539506590
|
17
|
+
test1,down,Failure,1539507591
|
18
|
+
test2,up,Success,1539508592
|
19
|
+
CSV
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with service parameter' do
|
23
|
+
context 'when service exists' do
|
24
|
+
subject { service.call('test1') }
|
25
|
+
let(:expected_table) do
|
26
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
27
|
+
+---------+--------+---------------------+
|
28
|
+
| Service | Status | Time |
|
29
|
+
+---------+--------+---------------------+
|
30
|
+
| test1 | up | 14.10.2018 08:43:10 |
|
31
|
+
| test1 | down | 14.10.2018 08:59:51 |
|
32
|
+
+---------+--------+---------------------+
|
33
|
+
TABLE
|
34
|
+
end
|
35
|
+
|
36
|
+
it { is_expected.to eq(expected_table) }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when service does not exists' do
|
40
|
+
subject { service.call('test3') }
|
41
|
+
let(:expected_table) do
|
42
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
43
|
+
+---------+--------+------+
|
44
|
+
| Service | Status | Time |
|
45
|
+
+---------+--------+------+
|
46
|
+
+---------+--------+------+
|
47
|
+
TABLE
|
48
|
+
end
|
49
|
+
|
50
|
+
it { is_expected.to eq(expected_table) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'without service parameter' do
|
55
|
+
subject { service.call }
|
56
|
+
let(:expected_table) do
|
57
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
58
|
+
+---------+--------+---------------------+
|
59
|
+
| Service | Status | Time |
|
60
|
+
+---------+--------+---------------------+
|
61
|
+
| test1 | up | 14.10.2018 08:43:10 |
|
62
|
+
| test1 | down | 14.10.2018 08:59:51 |
|
63
|
+
| test2 | up | 14.10.2018 09:16:32 |
|
64
|
+
+---------+--------+---------------------+
|
65
|
+
TABLE
|
66
|
+
end
|
67
|
+
|
68
|
+
it { is_expected.to eq(expected_table) }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BuildLogTable do
|
4
|
+
describe '#call' do
|
5
|
+
subject { described_class.new.call(records) }
|
6
|
+
|
7
|
+
context 'with records' do
|
8
|
+
let(:records) do
|
9
|
+
[
|
10
|
+
StatusPageRuby::Status.new('test1', 'up', 'Success', '1539506590'),
|
11
|
+
StatusPageRuby::Status.new('test2', 'up', 'Success', '1539508592')
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:expected_table) do
|
16
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
17
|
+
+---------+--------+---------------------+
|
18
|
+
| Service | Status | Time |
|
19
|
+
+---------+--------+---------------------+
|
20
|
+
| test1 | up | 14.10.2018 08:43:10 |
|
21
|
+
| test2 | up | 14.10.2018 09:16:32 |
|
22
|
+
+---------+--------+---------------------+
|
23
|
+
TABLE
|
24
|
+
end
|
25
|
+
|
26
|
+
it { is_expected.to eq(expected_table) }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with empty records' do
|
30
|
+
let(:records) { [] }
|
31
|
+
let(:expected_table) do
|
32
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
33
|
+
+---------+--------+------+
|
34
|
+
| Service | Status | Time |
|
35
|
+
+---------+--------+------+
|
36
|
+
+---------+--------+------+
|
37
|
+
TABLE
|
38
|
+
end
|
39
|
+
|
40
|
+
it { is_expected.to eq(expected_table) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::BuildStatsTable do
|
4
|
+
let(:data_file_path) { Tempfile.new('data_file_path').path }
|
5
|
+
let(:service) do
|
6
|
+
described_class.new(
|
7
|
+
StatusPageRuby::Repositories::Status.new(
|
8
|
+
StatusPageRuby::Storage.new(data_file_path)
|
9
|
+
)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#call' do
|
14
|
+
before do
|
15
|
+
Timecop.freeze(Time.at(1_539_520_990))
|
16
|
+
File.write(data_file_path, <<-CSV.delete(' '))
|
17
|
+
test1,up,Success,1539506590
|
18
|
+
test1,down,Failure,1539510190
|
19
|
+
test1,down,Failure,1539513790
|
20
|
+
test2,up,Success,1539519190
|
21
|
+
test1,up,Success,1539517390
|
22
|
+
CSV
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with service parameter' do
|
26
|
+
context 'when service exists' do
|
27
|
+
subject { service.call('test1') }
|
28
|
+
let(:expected_table) do
|
29
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
30
|
+
+---------+----------+-----------+
|
31
|
+
| Service | Up since | Down time |
|
32
|
+
+---------+----------+-----------+
|
33
|
+
| test1 | 1 hours | 2 hours |
|
34
|
+
+---------+----------+-----------+
|
35
|
+
TABLE
|
36
|
+
end
|
37
|
+
|
38
|
+
it { is_expected.to eq(expected_table) }
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when service does not exists' do
|
42
|
+
subject { service.call('test3') }
|
43
|
+
let(:expected_table) do
|
44
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
45
|
+
+---------+----------+-----------+
|
46
|
+
| Service | Up since | Down time |
|
47
|
+
+---------+----------+-----------+
|
48
|
+
+---------+----------+-----------+
|
49
|
+
TABLE
|
50
|
+
end
|
51
|
+
|
52
|
+
it { is_expected.to eq(expected_table) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'without service parameter' do
|
57
|
+
subject { service.call }
|
58
|
+
let(:expected_table) do
|
59
|
+
<<-TABLE.gsub(/^ +/, '').strip
|
60
|
+
+---------+------------+-----------+
|
61
|
+
| Service | Up since | Down time |
|
62
|
+
+---------+------------+-----------+
|
63
|
+
| test1 | 1 hours | 2 hours |
|
64
|
+
| test2 | 30 minutes | 0 minutes |
|
65
|
+
+---------+------------+-----------+
|
66
|
+
TABLE
|
67
|
+
end
|
68
|
+
|
69
|
+
it { is_expected.to eq(expected_table) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::PullStatuses do
|
4
|
+
let(:status_repository) { double }
|
5
|
+
let(:service) { described_class.new(status_repository) }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
context 'when there is page classes' do
|
9
|
+
let(:page_class) { double(open: page) }
|
10
|
+
let(:page) { double(class: double(name: 'TestPage'), success?: true, status: 'Success', time: 123) }
|
11
|
+
let(:status) { double }
|
12
|
+
before { allow(service).to receive(:page_classes) { [page_class] } }
|
13
|
+
|
14
|
+
it 'does not trigger create_batch for status_repository' do
|
15
|
+
expect(status_repository).to receive(:create_batch).with([status]).once
|
16
|
+
expect(StatusPageRuby::Status).to receive(:new).with('TestPage', 'up', 'Success', 123) { status }.once
|
17
|
+
service.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when there is no page classes' do
|
22
|
+
before { allow(service).to receive(:page_class?) { false } }
|
23
|
+
|
24
|
+
it 'does not trigger create_batch for status_repository' do
|
25
|
+
expect(status_repository).not_to receive(:create_batch)
|
26
|
+
service.call
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Services::RestoreData do
|
4
|
+
let(:storage) { double }
|
5
|
+
let(:service) { described_class.new(storage) }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
it 'triggers restore on storage' do
|
9
|
+
expect(storage).to receive(:restore).with('test_path').once
|
10
|
+
service.call('test_path')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe StatusPageRuby::Status do
|
4
|
+
describe '.new' do
|
5
|
+
[
|
6
|
+
[nil, nil, nil, nil],
|
7
|
+
['', '', '', ''],
|
8
|
+
[1, 2, 2, 3],
|
9
|
+
['Github', 'up', 'All Good', 1_539_506_590]
|
10
|
+
].each do |service, state, status, time|
|
11
|
+
context "with service: #{service}, state: #{state}, status: #{status} and time: #{time}" do
|
12
|
+
subject { described_class.new(service, state, status, time) }
|
13
|
+
|
14
|
+
it { expect(subject.service).to eq(service.to_s) }
|
15
|
+
it { expect(subject.state).to eq(state.to_s) }
|
16
|
+
it { expect(subject.time).to eq(time.to_s) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#record' do
|
22
|
+
[
|
23
|
+
[nil, nil, nil, nil],
|
24
|
+
['', '', '', ''],
|
25
|
+
[1, 2, 3, 4],
|
26
|
+
['Github', 'up', 'All Good', 1_539_506_590]
|
27
|
+
].each do |service, state, status, time|
|
28
|
+
context "with service: #{service}, state: #{state}, status: #{status} and time: #{time}" do
|
29
|
+
subject { described_class.new(service, state, status, time).record }
|
30
|
+
|
31
|
+
it { is_expected.to eq([service.to_s, state.to_s, status.to_s, time.to_s]) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#history_record' do
|
37
|
+
[
|
38
|
+
[[nil, nil, nil, 1_539_506_590], ['', '', '14.10.2018 08:43:10']],
|
39
|
+
[['', '', '', 1_539_506_590], ['', '', '14.10.2018 08:43:10']],
|
40
|
+
[[1, 2, 3, 1_539_506_590], ['1', '2', '14.10.2018 08:43:10']],
|
41
|
+
[['Github', 'up', 'All Good', 1_539_506_590], ['Github', 'up', '14.10.2018 08:43:10']]
|
42
|
+
].each do |args, result|
|
43
|
+
context "with service: #{args[0]}, state: #{args[1]}, status: #{args[2]} and time: #{args[3]}" do
|
44
|
+
subject { described_class.new(*args).history_record }
|
45
|
+
|
46
|
+
it { is_expected.to eq(result) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#to_csv' do
|
52
|
+
[
|
53
|
+
[[nil, nil, nil, nil], "\"\",\"\",\"\",\"\"\n"],
|
54
|
+
[['', '', '', ''], "\"\",\"\",\"\",\"\"\n"],
|
55
|
+
[[1, 2, 3, 4], "1,2,3,4\n"],
|
56
|
+
[['Github', 'up', 'All Good', 1_539_506_590], "Github,up,All Good,1539506590\n"]
|
57
|
+
].each do |args, result|
|
58
|
+
context "with service: #{args[0]}, state: #{args[1]}, status: #{args[2]} and time: #{args[3]}" do
|
59
|
+
subject { described_class.new(*args).to_csv }
|
60
|
+
|
61
|
+
it { is_expected.to eq(result) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|