datadog_backup 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/validate-pr.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/bin/datadog_backup +4 -1
- data/lib/datadog_backup/slos.rb +63 -0
- data/lib/datadog_backup/version.rb +1 -1
- data/lib/datadog_backup.rb +1 -0
- data/spec/datadog_backup/slos_spec.rb +207 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a99c7fdf81fb1fafa9e2c8b2c4e28a7a2685d4c1a6482eede1aefd08322167bc
|
4
|
+
data.tar.gz: ac4f8c37ac22dc4c9893153afa27678e4abb98d70a4cb2a47574bf26e1b5c8da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae3e46853cda4a9dc988624c169ad104c2a3737081f04ed5c33a1bfe6f24a752e6bd6fadfd0d9d1dc8545b135b95829044fd4748abd45ef6cd43c4d3258662d9
|
7
|
+
data.tar.gz: 39136571658e67c317b00a31b21b67169026e958cedf987dbb57c0b8af9a5cf8f944ed9617a1fd736a591aaa8c22559b4405fd5e17641dcf6fe911dac0484668
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# [3.3.0](https://github.com/scribd/datadog_backup/compare/v3.2.1...v3.3.0) (2023-08-17)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* backup SLOs ([#155](https://github.com/scribd/datadog_backup/issues/155)) ([6cca6e7](https://github.com/scribd/datadog_backup/commit/6cca6e7567895673e94c7de80022c821553698ee)), closes [#1](https://github.com/scribd/datadog_backup/issues/1)
|
7
|
+
|
1
8
|
## [3.2.1](https://github.com/scribd/datadog_backup/compare/v3.2.0...v3.2.1) (2023-02-11)
|
2
9
|
|
3
10
|
|
data/bin/datadog_backup
CHANGED
@@ -48,6 +48,9 @@ def prereqs(defaults) # rubocop:disable Metrics/AbcSize
|
|
48
48
|
opts.on('--dashboards-only') do
|
49
49
|
result[:resources] = [DatadogBackup::Dashboards]
|
50
50
|
end
|
51
|
+
opts.on('--slos-only') do
|
52
|
+
result[:resources] = [DatadogBackup::SLOs]
|
53
|
+
end
|
51
54
|
opts.on('--synthetics-only') do
|
52
55
|
result[:resources] = [DatadogBackup::Synthetics]
|
53
56
|
end
|
@@ -83,7 +86,7 @@ defaults = {
|
|
83
86
|
action: nil,
|
84
87
|
backup_dir: File.join(ENV.fetch('PWD'), 'backup'),
|
85
88
|
diff_format: :color,
|
86
|
-
resources: [DatadogBackup::Dashboards, DatadogBackup::Monitors, DatadogBackup::Synthetics],
|
89
|
+
resources: [DatadogBackup::Dashboards, DatadogBackup::Monitors, DatadogBackup::SLOs, DatadogBackup::Synthetics],
|
87
90
|
output_format: :yaml,
|
88
91
|
force_restore: false,
|
89
92
|
disable_array_sort: false
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DatadogBackup
|
4
|
+
# SLO specific overrides for backup and restore.
|
5
|
+
class SLOs < Resources
|
6
|
+
def all
|
7
|
+
get_all
|
8
|
+
end
|
9
|
+
|
10
|
+
def backup
|
11
|
+
LOGGER.info("Starting diffs on #{::DatadogBackup::ThreadPool::TPOOL.max_length} threads")
|
12
|
+
futures = all.map do |slo|
|
13
|
+
Concurrent::Promises.future_on(::DatadogBackup::ThreadPool::TPOOL, slo) do |board|
|
14
|
+
id = board[id_keyname]
|
15
|
+
get_and_write_file(id)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
watcher = ::DatadogBackup::ThreadPool.watcher
|
20
|
+
watcher.join if watcher.status
|
21
|
+
|
22
|
+
Concurrent::Promises.zip(*futures).value!
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_by_id(id)
|
26
|
+
begin
|
27
|
+
slo = except(get(id))
|
28
|
+
rescue Faraday::ResourceNotFound => e
|
29
|
+
slo = {}
|
30
|
+
end
|
31
|
+
except(slo)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(options)
|
35
|
+
super(options)
|
36
|
+
@banlist = %w[modified_at url].freeze
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the Faraday body from a response with a 2xx status code, otherwise raise an error
|
40
|
+
def body_with_2xx(response)
|
41
|
+
unless response.status.to_s =~ /^2/
|
42
|
+
raise "#{caller_locations(1,
|
43
|
+
1)[0].label} failed with error #{response.status}"
|
44
|
+
end
|
45
|
+
|
46
|
+
response.body.fetch('data')
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def api_version
|
52
|
+
'v1'
|
53
|
+
end
|
54
|
+
|
55
|
+
def api_resource_name
|
56
|
+
'slo'
|
57
|
+
end
|
58
|
+
|
59
|
+
def id_keyname
|
60
|
+
'id'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/datadog_backup.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative 'datadog_backup/cli'
|
|
8
8
|
require_relative 'datadog_backup/resources'
|
9
9
|
require_relative 'datadog_backup/dashboards'
|
10
10
|
require_relative 'datadog_backup/monitors'
|
11
|
+
require_relative 'datadog_backup/slos'
|
11
12
|
require_relative 'datadog_backup/synthetics'
|
12
13
|
require_relative 'datadog_backup/thread_pool'
|
13
14
|
require_relative 'datadog_backup/version'
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe DatadogBackup::SLOs do
|
6
|
+
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
7
|
+
let(:api_client_double) { Faraday.new { |f| f.adapter :test, stubs } }
|
8
|
+
let(:tempdir) { Dir.mktmpdir }
|
9
|
+
let(:slos) do
|
10
|
+
slos = described_class.new(
|
11
|
+
action: 'backup',
|
12
|
+
backup_dir: tempdir,
|
13
|
+
output_format: :json,
|
14
|
+
resources: []
|
15
|
+
)
|
16
|
+
allow(slos).to receive(:api_service).and_return(api_client_double)
|
17
|
+
return slos
|
18
|
+
end
|
19
|
+
let(:fetched_slos) do
|
20
|
+
{
|
21
|
+
"data"=>[
|
22
|
+
{"id"=>"abc-123", "name"=>"CI Stability", "tags"=>["kind:availability", "team:my_team"], "monitor_tags"=>[], "thresholds"=>[{"timeframe"=>"7d", "target"=>98.0, "target_display"=>"98."}, {"timeframe"=>"30d", "target"=>98.0, "target_display"=>"98."}, {"timeframe"=>"90d", "target"=>98.0, "target_display"=>"98."}], "type"=>"metric", "type_id"=>1, "description"=>"something helpful", "timeframe"=>"30d", "target_threshold"=>98.0, "query"=>{"denominator"=>"sum:metric.ci_things{*}.as_count()", "numerator"=>"sum:metric.ci_things{*}.as_count()-sum:metric.ci_things{infra_failure}.as_count()"}, "creator"=>{"name"=>"Thelma Patterson", "handle"=>"thelma.patterson@example.com", "email"=>"thelma.patterson@example.com"}, "created_at"=>1571335531, "modified_at"=>1687844157},
|
23
|
+
{"id"=>"sbc-124", "name"=>"A Latency SLO", "tags"=>["team:my_team", "kind:latency"], "monitor_tags"=>[], "thresholds"=>[{"timeframe"=>"7d", "target"=>95.0, "target_display"=>"95."}, {"timeframe"=>"30d", "target"=>95.0, "target_display"=>"95."}, {"timeframe"=>"90d", "target"=>95.0, "target_display"=>"95."}], "type"=>"monitor", "type_id"=>0, "description"=>"", "timeframe"=>"30d", "target_threshold"=>95.0, "monitor_ids"=>[13158755], "creator"=>{"name"=>"Louise Montague", "handle"=>"louise.montague@example.com", "email"=>"louise.montague@example.com"}, "created_at"=>1573162531, "modified_at"=>1685819875}
|
24
|
+
],
|
25
|
+
"errors"=>[],
|
26
|
+
"metadata"=>{"page"=>{"total_count"=>359, "total_filtered_count"=>359}}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
let(:slo_abc_123) do
|
30
|
+
{
|
31
|
+
"id" => "abc-123",
|
32
|
+
"name" => "CI Stability",
|
33
|
+
"tags" => [
|
34
|
+
"kind:availability",
|
35
|
+
"team:my_team",
|
36
|
+
],
|
37
|
+
"monitor_tags" => [],
|
38
|
+
"thresholds" => [
|
39
|
+
{
|
40
|
+
"timeframe" => "7d",
|
41
|
+
"target" => 98.0,
|
42
|
+
"target_display" => "98."
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"timeframe" => "30d",
|
46
|
+
"target" => 98.0,
|
47
|
+
"target_display" => "98."
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"timeframe" => "90d",
|
51
|
+
"target" => 98.0,
|
52
|
+
"target_display" => "98."
|
53
|
+
}
|
54
|
+
],
|
55
|
+
"type" => "metric",
|
56
|
+
"type_id" => 1,
|
57
|
+
"description" => "something helpful",
|
58
|
+
"timeframe" => "30d",
|
59
|
+
"target_threshold" => 98.0,
|
60
|
+
"query" => {
|
61
|
+
"denominator" => "sum:metric.ci_things{*}.as_count()",
|
62
|
+
"numerator" => "sum:metric.ci_things{*}.as_count()-sum:metric.ci_things{infra_failure}.as_count()"
|
63
|
+
},
|
64
|
+
"creator" => {
|
65
|
+
"name" => "Thelma Patterson",
|
66
|
+
"handle" => "thelma.patterson@example.com",
|
67
|
+
"email" => "thelma.patterson@example.com"
|
68
|
+
},
|
69
|
+
"created_at" => 1571335531,
|
70
|
+
"modified_at" => 1687844157
|
71
|
+
}
|
72
|
+
end
|
73
|
+
let(:slo_sbc_124) do
|
74
|
+
{
|
75
|
+
"id" => "sbc-124",
|
76
|
+
"name" => "A Latency SLO",
|
77
|
+
"tags" => [
|
78
|
+
"kind:latency",
|
79
|
+
"team:my_team",
|
80
|
+
],
|
81
|
+
"monitor_tags" => [],
|
82
|
+
"thresholds" => [
|
83
|
+
{
|
84
|
+
"timeframe" => "7d",
|
85
|
+
"target" => 98.0,
|
86
|
+
"target_display" => "98."
|
87
|
+
},
|
88
|
+
{
|
89
|
+
"timeframe" => "30d",
|
90
|
+
"target" => 98.0,
|
91
|
+
"target_display" => "98."
|
92
|
+
},
|
93
|
+
{
|
94
|
+
"timeframe" => "90d",
|
95
|
+
"target" => 98.0,
|
96
|
+
"target_display" => "98."
|
97
|
+
}
|
98
|
+
],
|
99
|
+
"type" => "monitor",
|
100
|
+
"type_id"=>0,
|
101
|
+
"description"=>"",
|
102
|
+
"timeframe"=>"30d",
|
103
|
+
"target_threshold"=>95.0,
|
104
|
+
"monitor_ids"=>[ 13158755 ],
|
105
|
+
"creator"=>{
|
106
|
+
"name"=>"Louise Montague",
|
107
|
+
"handle"=>"louise.montague@example.com",
|
108
|
+
"email"=>"louise.montague@example.com"
|
109
|
+
},
|
110
|
+
"created_at"=>1573162531,
|
111
|
+
"modified_at"=>1685819875
|
112
|
+
}
|
113
|
+
end
|
114
|
+
let(:slo_abc_123_response) do
|
115
|
+
{ "data" => slo_abc_123, "errors" => [] }
|
116
|
+
end
|
117
|
+
let(:slo_sbc_124_response) do
|
118
|
+
{ "data" => slo_sbc_124, "errors" => [] }
|
119
|
+
end
|
120
|
+
let(:all_slos) { respond_with200(fetched_slos) }
|
121
|
+
let(:example_slo1) { respond_with200(slo_abc_123_response) }
|
122
|
+
let(:example_slo2) { respond_with200(slo_sbc_124_response) }
|
123
|
+
|
124
|
+
before do
|
125
|
+
stubs.get('/api/v1/slo') { all_slos }
|
126
|
+
stubs.get('/api/v1/slo/abc-123') { example_slo1 }
|
127
|
+
stubs.get('/api/v1/slo/sbc-124') { example_slo2 }
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#backup' do
|
131
|
+
subject { slos.backup }
|
132
|
+
|
133
|
+
it 'is expected to create two files' do
|
134
|
+
file1 = instance_double(File)
|
135
|
+
allow(File).to receive(:open).with(slos.filename('abc-123'), 'w').and_return(file1)
|
136
|
+
allow(file1).to receive(:write)
|
137
|
+
allow(file1).to receive(:close)
|
138
|
+
|
139
|
+
file2 = instance_double(File)
|
140
|
+
allow(File).to receive(:open).with(slos.filename('sbc-124'), 'w').and_return(file2)
|
141
|
+
allow(file2).to receive(:write)
|
142
|
+
allow(file2).to receive(:close)
|
143
|
+
|
144
|
+
slos.backup
|
145
|
+
expect(file1).to have_received(:write).with(::JSON.pretty_generate(slo_abc_123.deep_sort))
|
146
|
+
expect(file2).to have_received(:write).with(::JSON.pretty_generate(slo_sbc_124.deep_sort))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#filename' do
|
151
|
+
subject { slos.filename('abc-123') }
|
152
|
+
|
153
|
+
it { is_expected.to eq("#{tempdir}/slos/abc-123.json") }
|
154
|
+
end
|
155
|
+
|
156
|
+
describe '#get_by_id' do
|
157
|
+
subject { slos.get_by_id('abc-123') }
|
158
|
+
|
159
|
+
it { is_expected.to eq slo_abc_123 }
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '#diff' do
|
163
|
+
it 'calls the api only once' do
|
164
|
+
slos.write_file('{"a":"b"}', slos.filename('abc-123'))
|
165
|
+
expect(slos.diff('abc-123')).to eq(<<~EODASH
|
166
|
+
---
|
167
|
+
-created_at: 1571335531
|
168
|
+
-creator:
|
169
|
+
- email: thelma.patterson@example.com
|
170
|
+
- handle: thelma.patterson@example.com
|
171
|
+
- name: Thelma Patterson
|
172
|
+
-description: something helpful
|
173
|
+
-id: abc-123
|
174
|
+
-monitor_tags: []
|
175
|
+
-name: CI Stability
|
176
|
+
-query:
|
177
|
+
- denominator: sum:metric.ci_things{*}.as_count()
|
178
|
+
- numerator: sum:metric.ci_things{*}.as_count()-sum:metric.ci_things{infra_failure}.as_count()
|
179
|
+
-tags:
|
180
|
+
-- kind:availability
|
181
|
+
-- team:my_team
|
182
|
+
-target_threshold: 98.0
|
183
|
+
-thresholds:
|
184
|
+
-- target: 98.0
|
185
|
+
- target_display: '98.'
|
186
|
+
- timeframe: 30d
|
187
|
+
-- target: 98.0
|
188
|
+
- target_display: '98.'
|
189
|
+
- timeframe: 7d
|
190
|
+
-- target: 98.0
|
191
|
+
- target_display: '98.'
|
192
|
+
- timeframe: 90d
|
193
|
+
-timeframe: 30d
|
194
|
+
-type: metric
|
195
|
+
-type_id: 1
|
196
|
+
+a: b
|
197
|
+
EODASH
|
198
|
+
.chomp)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#except' do
|
203
|
+
subject { slos.except({ :a => :b, 'modified_at' => :c, 'url' => :d }) }
|
204
|
+
|
205
|
+
it { is_expected.to eq({ a: :b }) }
|
206
|
+
end
|
207
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datadog_backup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kamran Farhadi
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-08-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: amazing_print
|
@@ -229,6 +229,7 @@ files:
|
|
229
229
|
- lib/datadog_backup/monitors.rb
|
230
230
|
- lib/datadog_backup/options.rb
|
231
231
|
- lib/datadog_backup/resources.rb
|
232
|
+
- lib/datadog_backup/slos.rb
|
232
233
|
- lib/datadog_backup/synthetics.rb
|
233
234
|
- lib/datadog_backup/thread_pool.rb
|
234
235
|
- lib/datadog_backup/version.rb
|
@@ -239,6 +240,7 @@ files:
|
|
239
240
|
- spec/datadog_backup/deprecations_spec.rb
|
240
241
|
- spec/datadog_backup/local_filesystem_spec.rb
|
241
242
|
- spec/datadog_backup/monitors_spec.rb
|
243
|
+
- spec/datadog_backup/slos_spec.rb
|
242
244
|
- spec/datadog_backup/synthetics_spec.rb
|
243
245
|
- spec/datadog_backup_bin_spec.rb
|
244
246
|
- spec/spec_helper.rb
|