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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e3e8528c064d05b09bd31080a7bcab7c77fcca8dde46949cf8c62a7702f2af1
4
- data.tar.gz: 24c57007224fcf546b5a886e4b9f2a78f76b2a63fd2c64067ae2454192919848
3
+ metadata.gz: a99c7fdf81fb1fafa9e2c8b2c4e28a7a2685d4c1a6482eede1aefd08322167bc
4
+ data.tar.gz: ac4f8c37ac22dc4c9893153afa27678e4abb98d70a4cb2a47574bf26e1b5c8da
5
5
  SHA512:
6
- metadata.gz: d5180a6ba1f92f5db842e88d337878eacd0bafe114fbbb8752153b85f7c47f682be3bdd529b694294cc5523fe4c94274a7ee78d15fc4798b327598fb7710303b
7
- data.tar.gz: f4ccccd735136f06f92cc71f1df0176e5fa626fd36f5e60f4bc88ef93f9fcf31f8d840c523e1e70f08195faf8d32e8522fea3665e9b6f1efe280cf8b214331a9
6
+ metadata.gz: ae3e46853cda4a9dc988624c169ad104c2a3737081f04ed5c33a1bfe6f24a752e6bd6fadfd0d9d1dc8545b135b95829044fd4748abd45ef6cd43c4d3258662d9
7
+ data.tar.gz: 39136571658e67c317b00a31b21b67169026e958cedf987dbb57c0b8af9a5cf8f944ed9617a1fd736a591aaa8c22559b4405fd5e17641dcf6fe911dac0484668
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-20.04
11
11
  steps:
12
12
  - name: Validate PR Title
13
- uses: amannn/action-semantic-pull-request@v5.0.2
13
+ uses: amannn/action-semantic-pull-request@v5.2.0
14
14
  env:
15
15
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16
16
  with:
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
- VERSION = '3.2.1'
4
+ VERSION = '3.3.0'
5
5
  end
@@ -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.2.1
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-02-11 00:00:00.000000000 Z
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