datadog_backup 3.2.1 → 3.3.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.
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