datadog_backup 0.10.1.alpha.1 → 0.11.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 +4 -4
- data/.github/workflows/rspec_and_release.yml +6 -6
- data/.gitignore +2 -0
- data/CHANGELOG.md +22 -1
- data/Guardfile +1 -1
- data/bin/datadog_backup +4 -0
- data/datadog_backup.gemspec +2 -2
- data/example/Gemfile +3 -1
- data/lib/datadog_backup/cli.rb +21 -18
- data/lib/datadog_backup/core.rb +30 -41
- data/lib/datadog_backup/dashboards.rb +4 -11
- data/lib/datadog_backup/local_filesystem.rb +7 -5
- data/lib/datadog_backup/monitors.rb +7 -11
- data/lib/datadog_backup/options.rb +4 -0
- data/lib/datadog_backup/thread_pool.rb +1 -1
- data/lib/datadog_backup/version.rb +1 -1
- data/spec/datadog_backup/cli_spec.rb +11 -9
- data/spec/datadog_backup/core_spec.rb +18 -35
- data/spec/datadog_backup/dashboards_spec.rb +23 -9
- data/spec/datadog_backup/monitors_spec.rb +9 -12
- data/spec/spec_helper.rb +2 -0
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9cfe289fb044024544f602c71cf219df872f7a624d5400cdfa38fca04a063cc4
|
4
|
+
data.tar.gz: 1f646899a202ea0ddc5516135d9c9ffdb01f13e4b99a5f2a4d72222d9fb43169
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6fbcc8eb4385edd4ad17a3f4f29b26d15e33d1696337b7d9f7f74fb877627a1214f425f3aa2294206017757f77eb67b113da30a25b6c5446ecbe46bceb381a4
|
7
|
+
data.tar.gz: f6576125ca22711b2f0102798f46cae7fd896cb006736a5c32ef75f76a720d663aa6970a87c67854461dafe0c64ebbcb489b1fc0eda6ac21750893420f479962
|
@@ -11,10 +11,10 @@ jobs:
|
|
11
11
|
|
12
12
|
steps:
|
13
13
|
- uses: actions/checkout@v2
|
14
|
-
- name: Set up Ruby 2.7.
|
15
|
-
uses: actions/setup-ruby@v1.1.
|
14
|
+
- name: Set up Ruby 2.7.2
|
15
|
+
uses: actions/setup-ruby@v1.1.2
|
16
16
|
with:
|
17
|
-
ruby-version: 2.7.
|
17
|
+
ruby-version: 2.7.2
|
18
18
|
- name: Test with Rspec
|
19
19
|
run: |
|
20
20
|
gem install --no-document bundler
|
@@ -27,10 +27,10 @@ jobs:
|
|
27
27
|
|
28
28
|
steps:
|
29
29
|
- uses: actions/checkout@v2
|
30
|
-
- name: Set up Ruby 2.7.
|
31
|
-
uses: actions/setup-ruby@v1.1.
|
30
|
+
- name: Set up Ruby 2.7.2
|
31
|
+
uses: actions/setup-ruby@v1.1.2
|
32
32
|
with:
|
33
|
-
ruby-version: 2.7.
|
33
|
+
ruby-version: 2.7.2
|
34
34
|
- name: Build with bundler
|
35
35
|
run: |
|
36
36
|
gem install --no-document bundler
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,25 @@
|
|
1
|
-
|
1
|
+
# [0.11.0](https://github.com/scribd/datadog_backup/compare/v0.10.3...v0.11.0) (2021-01-12)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* Add force-restore flag to allow running in automation ([#46](https://github.com/scribd/datadog_backup/issues/46)) ([e067386](https://github.com/scribd/datadog_backup/commit/e0673862b6f6d86297e1352faaee872f2c4884c8))
|
7
|
+
|
8
|
+
## [0.10.3](https://github.com/scribd/datadog_backup/compare/v0.10.2...v0.10.3) (2020-12-11)
|
9
|
+
|
10
|
+
|
11
|
+
### Performance Improvements
|
12
|
+
|
13
|
+
* coerce patch release ([bc86649](https://github.com/scribd/datadog_backup/commit/bc86649b874cd5be1da2f6bc0d1b1ecd0728676c))
|
14
|
+
|
15
|
+
## [0.10.2](https://github.com/scribd/datadog_backup/compare/v0.10.1...v0.10.2) (2020-11-03)
|
16
|
+
|
17
|
+
|
18
|
+
### Bug Fixes
|
19
|
+
|
20
|
+
* virtual environment updates ruby 2.7.1 -> 2.7.2 ([f950dd6](https://github.com/scribd/datadog_backup/commit/f950dd67ce989bb12de5f2dbf69c6449b91f2542))
|
21
|
+
|
22
|
+
## [0.10.1](https://github.com/scribd/datadog_backup/compare/v0.10.0...v0.10.1) (2020-09-08)
|
2
23
|
|
3
24
|
|
4
25
|
### Bug Fixes
|
data/Guardfile
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
#
|
18
18
|
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
19
19
|
|
20
|
-
#
|
20
|
+
# NOTE: The cmd option is now required due to the increasing number of ways
|
21
21
|
# rspec may be run, below are examples of the most common uses.
|
22
22
|
# * bundler: 'bundle exec rspec'
|
23
23
|
# * bundler binstubs: 'bin/rspec'
|
data/bin/datadog_backup
CHANGED
@@ -23,6 +23,7 @@ LOGGER.level = Logger::INFO
|
|
23
23
|
diff_format: :color,
|
24
24
|
resources: [DatadogBackup::Dashboards, DatadogBackup::Monitors],
|
25
25
|
output_format: :yaml,
|
26
|
+
force_restore: false,
|
26
27
|
logger: LOGGER
|
27
28
|
}
|
28
29
|
|
@@ -63,6 +64,9 @@ def prereqs
|
|
63
64
|
opts.on('--diff-format FORMAT', 'one of `color`, `html_simple`, `html`') do |format|
|
64
65
|
@options[:diff_format] = format.to_sym
|
65
66
|
end
|
67
|
+
opts.on('--force-restore', 'force restore to Datadog') do
|
68
|
+
@options[:force_restore] = true
|
69
|
+
end
|
66
70
|
end
|
67
71
|
options.parse!
|
68
72
|
|
data/datadog_backup.gemspec
CHANGED
@@ -19,12 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^spec/})
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
-
spec.add_dependency 'amazing_print', '1.2.
|
22
|
+
spec.add_dependency 'amazing_print', '1.2.2'
|
23
23
|
spec.add_dependency 'concurrent-ruby', '1.1.7'
|
24
24
|
spec.add_dependency 'concurrent-ruby-edge', '0.6.0'
|
25
25
|
spec.add_dependency 'deepsort', '0.4.5'
|
26
26
|
spec.add_dependency 'diffy', '3.4.0'
|
27
|
-
spec.add_dependency 'dogapi', '1.
|
27
|
+
spec.add_dependency 'dogapi', '1.44.0'
|
28
28
|
|
29
29
|
spec.add_development_dependency 'bundler'
|
30
30
|
spec.add_development_dependency 'pry'
|
data/example/Gemfile
CHANGED
data/lib/datadog_backup/cli.rb
CHANGED
@@ -91,7 +91,7 @@ module DatadogBackup
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def matching_resource_instance(klass)
|
94
|
-
resource_instances.select { |resource_instance| resource_instance.
|
94
|
+
resource_instances.select { |resource_instance| resource_instance.instance_of?(klass) }.first
|
95
95
|
end
|
96
96
|
|
97
97
|
def resource_instances
|
@@ -108,27 +108,30 @@ module DatadogBackup
|
|
108
108
|
id, diff = *future.value!
|
109
109
|
next unless diff
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
puts '(r)estore to Datadog, overwrite local changes and (d)ownload, (s)kip, or (q)uit?'
|
114
|
-
response = $stdin.gets.chomp
|
115
|
-
case response
|
116
|
-
when 'q'
|
117
|
-
exit
|
118
|
-
when 'r'
|
119
|
-
puts "Restoring #{id} to Datadog."
|
120
|
-
definitive_resource_instance(id).update_with_200(id, definitive_resource_instance(id).load_from_file_by_id(id))
|
121
|
-
when 'd'
|
122
|
-
puts "Downloading #{id} from Datadog."
|
123
|
-
definitive_resource_instance(id).get_and_write_file(id)
|
124
|
-
when 's'
|
125
|
-
next
|
111
|
+
if @options[:force_restore]
|
112
|
+
definitive_resource_instance(id).update(id, definitive_resource_instance(id).load_from_file_by_id(id))
|
126
113
|
else
|
127
|
-
puts '
|
114
|
+
puts '--------------------------------------------------------------------------------'
|
115
|
+
puts format_diff_output([id, diff])
|
116
|
+
puts '(r)estore to Datadog, overwrite local changes and (d)ownload, (s)kip, or (q)uit?'
|
128
117
|
response = $stdin.gets.chomp
|
118
|
+
case response
|
119
|
+
when 'q'
|
120
|
+
exit
|
121
|
+
when 'r'
|
122
|
+
puts "Restoring #{id} to Datadog."
|
123
|
+
definitive_resource_instance(id).update(id, definitive_resource_instance(id).load_from_file_by_id(id))
|
124
|
+
when 'd'
|
125
|
+
puts "Downloading #{id} from Datadog."
|
126
|
+
definitive_resource_instance(id).get_and_write_file(id)
|
127
|
+
when 's'
|
128
|
+
next
|
129
|
+
else
|
130
|
+
puts 'Invalid response, please try again.'
|
131
|
+
response = $stdin.gets.chomp
|
132
|
+
end
|
129
133
|
end
|
130
134
|
end
|
131
|
-
|
132
135
|
watcher.join if watcher.status
|
133
136
|
end
|
134
137
|
|
data/lib/datadog_backup/core.rb
CHANGED
@@ -24,55 +24,48 @@ module DatadogBackup
|
|
24
24
|
raise 'subclass is expected to implement #backup'
|
25
25
|
end
|
26
26
|
|
27
|
-
# Calls out to Datadog and checks for a '200' response
|
28
|
-
def client_with_200(method, *id)
|
29
|
-
max_retries = 6
|
30
|
-
retries ||= 0
|
31
|
-
|
32
|
-
response = client.send(method, *id)
|
33
|
-
|
34
|
-
# logger.debug response
|
35
|
-
raise "Method #{method} failed with error #{response}" unless response[0] == '200'
|
36
|
-
|
37
|
-
response[1]
|
38
|
-
rescue ::Net::OpenTimeout => e
|
39
|
-
if (retries += 1) <= max_retries
|
40
|
-
sleep(0.1 * retries**5) # 0.1, 3.2, 24.3, 102.4 seconds per retry
|
41
|
-
retry
|
42
|
-
else
|
43
|
-
raise "Method #{method} failed with error #{e.message}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
27
|
# Returns the diffy diff.
|
48
28
|
# Optionally, supply an array of keys to remove from comparison
|
49
|
-
def diff(id
|
50
|
-
current = except(get_by_id(id)
|
51
|
-
filesystem = except(load_from_file_by_id(id)
|
29
|
+
def diff(id)
|
30
|
+
current = except(get_by_id(id)).deep_sort.to_yaml
|
31
|
+
filesystem = except(load_from_file_by_id(id)).deep_sort.to_yaml
|
52
32
|
result = ::Diffy::Diff.new(current, filesystem, include_plus_and_minus_in_html: true).to_s(diff_format)
|
53
33
|
logger.debug("Compared ID #{id} and found #{result}")
|
54
34
|
result
|
55
35
|
end
|
56
36
|
|
57
37
|
# Returns a hash with banlist elements removed
|
58
|
-
def except(hash
|
38
|
+
def except(hash)
|
59
39
|
hash.tap do # tap returns self
|
60
|
-
banlist.each do |key|
|
40
|
+
@banlist.each do |key|
|
61
41
|
hash.delete(key) # delete returns the value at the deleted key, hence the tap wrapper
|
62
42
|
end
|
63
43
|
end
|
64
44
|
end
|
65
45
|
|
46
|
+
def get(id)
|
47
|
+
with_200 do
|
48
|
+
api_service.request(Net::HTTP::Get, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, nil, false)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_all
|
53
|
+
with_200 do
|
54
|
+
api_service.request(Net::HTTP::Get, "/api/#{api_version}/#{api_resource_name}", nil, nil, false)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
66
58
|
def get_and_write_file(id)
|
67
59
|
write_file(dump(get_by_id(id)), filename(id))
|
68
60
|
end
|
69
61
|
|
70
|
-
def get_by_id(
|
71
|
-
|
62
|
+
def get_by_id(id)
|
63
|
+
except(get(id))
|
72
64
|
end
|
73
65
|
|
74
66
|
def initialize(options)
|
75
67
|
@options = options
|
68
|
+
@banlist = []
|
76
69
|
::FileUtils.mkdir_p(mydir)
|
77
70
|
end
|
78
71
|
|
@@ -80,25 +73,20 @@ module DatadogBackup
|
|
80
73
|
self.class.to_s.split(':').last.downcase
|
81
74
|
end
|
82
75
|
|
83
|
-
|
84
|
-
raise 'subclass is expected to implement #restore'
|
85
|
-
end
|
86
|
-
|
76
|
+
# Calls out to Datadog and checks for a '200' response
|
87
77
|
def update(id, body)
|
88
|
-
|
78
|
+
with_200 do
|
79
|
+
api_service.request(Net::HTTP::Put, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, body, true)
|
80
|
+
end
|
81
|
+
logger.warn 'Successfully restored to datadog.'
|
89
82
|
end
|
90
83
|
|
91
|
-
|
92
|
-
def update_with_200(id, body)
|
84
|
+
def with_200
|
93
85
|
max_retries = 6
|
94
86
|
retries ||= 0
|
95
87
|
|
96
|
-
response =
|
97
|
-
|
98
|
-
# logger.debug response
|
99
|
-
raise "Update failed with error #{response}" unless response[0] == '200'
|
100
|
-
|
101
|
-
logger.warn "Successfully restored #{id} to datadog."
|
88
|
+
response = yield
|
89
|
+
raise "Request failed with error #{response}" unless response[0] == '200'
|
102
90
|
|
103
91
|
response[1]
|
104
92
|
rescue ::Net::OpenTimeout => e
|
@@ -106,8 +94,9 @@ module DatadogBackup
|
|
106
94
|
sleep(0.1 * retries**5) # 0.1, 3.2, 24.3, 102.4 seconds per retry
|
107
95
|
retry
|
108
96
|
else
|
109
|
-
raise "
|
97
|
+
raise "Request failed with error #{e.message}"
|
110
98
|
end
|
111
99
|
end
|
100
|
+
|
112
101
|
end
|
113
102
|
end
|
@@ -2,10 +2,8 @@
|
|
2
2
|
|
3
3
|
module DatadogBackup
|
4
4
|
class Dashboards < Core
|
5
|
-
BANLIST = %w[modified_at url]
|
6
|
-
|
7
5
|
def all_boards
|
8
|
-
|
6
|
+
get_all.fetch('dashboards')
|
9
7
|
end
|
10
8
|
|
11
9
|
def api_service
|
@@ -37,14 +35,9 @@ module DatadogBackup
|
|
37
35
|
Concurrent::Promises.zip(*futures).value!
|
38
36
|
end
|
39
37
|
|
40
|
-
def
|
41
|
-
super(
|
42
|
-
|
43
|
-
|
44
|
-
def get_by_id(id)
|
45
|
-
except(client_with_200(:get_board, id), BANLIST)
|
38
|
+
def initialize(options)
|
39
|
+
super(options)
|
40
|
+
@banlist = %w[modified_at url].freeze
|
46
41
|
end
|
47
|
-
|
48
|
-
def restore!; end
|
49
42
|
end
|
50
43
|
end
|
@@ -31,9 +31,10 @@ module DatadogBackup
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def dump(object)
|
34
|
-
|
34
|
+
case output_format
|
35
|
+
when :json
|
35
36
|
JSON.pretty_generate(object.deep_sort)
|
36
|
-
|
37
|
+
when :yaml
|
37
38
|
YAML.dump(object.deep_sort)
|
38
39
|
else
|
39
40
|
raise 'invalid output_format specified or not specified'
|
@@ -45,7 +46,7 @@ module DatadogBackup
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def file_type(filepath)
|
48
|
-
::File.extname(filepath).strip.downcase[1
|
49
|
+
::File.extname(filepath).strip.downcase[1..].to_sym
|
49
50
|
end
|
50
51
|
|
51
52
|
def find_file_by_id(id)
|
@@ -53,9 +54,10 @@ module DatadogBackup
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def load_from_file(string, output_format)
|
56
|
-
|
57
|
+
case output_format
|
58
|
+
when :json
|
57
59
|
JSON.parse(string)
|
58
|
-
|
60
|
+
when :yaml
|
59
61
|
YAML.safe_load(string)
|
60
62
|
else
|
61
63
|
raise 'invalid output_format specified or not specified'
|
@@ -1,12 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DatadogBackup
|
4
|
-
class Monitors < Core
|
5
|
-
API_SERVICE_NAME = :@monitor_svc
|
6
|
-
BANLIST = %w[overall_state overall_state_modified matching_downtimes modified]
|
7
|
-
|
4
|
+
class Monitors < Core
|
8
5
|
def all_monitors
|
9
|
-
@all_monitors ||=
|
6
|
+
@all_monitors ||= get_all
|
10
7
|
end
|
11
8
|
|
12
9
|
def api_service
|
@@ -29,14 +26,13 @@ module DatadogBackup
|
|
29
26
|
end
|
30
27
|
end
|
31
28
|
|
32
|
-
def diff(id)
|
33
|
-
super(id, BANLIST)
|
34
|
-
end
|
35
|
-
|
36
29
|
def get_by_id(id)
|
37
|
-
except(all_monitors.select { |monitor| monitor['id'].to_s == id.to_s }.first
|
30
|
+
except(all_monitors.select { |monitor| monitor['id'].to_s == id.to_s }.first)
|
38
31
|
end
|
39
32
|
|
40
|
-
def
|
33
|
+
def initialize(options)
|
34
|
+
super(options)
|
35
|
+
@banlist = %w[overall_state overall_state_modified matching_downtimes modified].freeze
|
36
|
+
end
|
41
37
|
end
|
42
38
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe DatadogBackup::Cli do
|
6
|
+
let(:api_service_double) { double(Dogapi::APIService) }
|
6
7
|
let(:client_double) { double }
|
7
8
|
let(:tempdir) { Dir.mktmpdir }
|
8
9
|
let(:options) do
|
@@ -43,8 +44,10 @@ describe DatadogBackup::Cli do
|
|
43
44
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/alsostillthere.json")
|
44
45
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/deleted.json")
|
45
46
|
|
46
|
-
allow(client_double).to receive(:
|
47
|
-
allow(
|
47
|
+
allow(client_double).to receive(:instance_variable_get).with(:@dashboard_service).and_return(api_service_double)
|
48
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/dashboard", nil, nil, false).and_return(all_boards)
|
49
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/dashboard/stillthere", nil, nil, false).and_return(['200', {}])
|
50
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/dashboard/alsostillthere", nil, nil, false).and_return(['200', {}])
|
48
51
|
end
|
49
52
|
|
50
53
|
it 'deletes the file locally as well' do
|
@@ -83,17 +86,16 @@ describe DatadogBackup::Cli do
|
|
83
86
|
|
84
87
|
example 'starts interactive restore' do
|
85
88
|
allow($stdin).to receive(:gets).and_return('q')
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
89
|
+
|
90
|
+
expect { subject }.to(
|
91
|
+
output(/\(r\)estore to Datadog, overwrite local changes and \(d\)ownload, \(s\)kip, or \(q\)uit\?/).to_stdout
|
92
|
+
.and(raise_error(SystemExit))
|
93
|
+
)
|
92
94
|
end
|
93
95
|
|
94
96
|
example 'restore' do
|
95
97
|
allow($stdin).to receive(:gets).and_return('r')
|
96
|
-
expect(dashboards).to receive(:
|
98
|
+
expect(dashboards).to receive(:update).with('diffs1', { 'text' => 'diff' })
|
97
99
|
subject
|
98
100
|
end
|
99
101
|
example 'download' do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe DatadogBackup::Core do
|
@@ -22,21 +24,15 @@ describe DatadogBackup::Core do
|
|
22
24
|
it { is_expected.to eq client_double }
|
23
25
|
end
|
24
26
|
|
25
|
-
describe '#
|
26
|
-
subject { core.client_with_200(:get_all_boards) }
|
27
|
-
|
27
|
+
describe '#with_200' do
|
28
28
|
context 'with 200' do
|
29
|
-
|
30
|
-
allow(client_double).to receive(:get_all_boards).and_return(['200', { foo: :bar }])
|
31
|
-
end
|
29
|
+
subject { core.with_200 {['200', { foo: :bar }]} }
|
32
30
|
|
33
31
|
it { is_expected.to eq({ foo: :bar }) }
|
34
32
|
end
|
35
33
|
|
36
34
|
context 'with not 200' do
|
37
|
-
|
38
|
-
allow(client_double).to receive(:get_all_boards).and_return(['401', {}])
|
39
|
-
end
|
35
|
+
subject { core.with_200 {['400', "Error message"]} }
|
40
36
|
|
41
37
|
it 'raises an error' do
|
42
38
|
expect { subject }.to raise_error(RuntimeError)
|
@@ -50,34 +46,21 @@ describe DatadogBackup::Core do
|
|
50
46
|
core.write_file('{"text": "diff2", "extra": "diff2"}', "#{tempdir}/core/diff.json")
|
51
47
|
end
|
52
48
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
}
|
64
|
-
end
|
65
|
-
|
66
|
-
context 'with banlist' do
|
67
|
-
subject { core.diff('diff', ['extra']) }
|
68
|
-
it {
|
69
|
-
is_expected.to eq <<~EOF
|
70
|
-
---
|
71
|
-
-text: diff1
|
72
|
-
+text: diff2
|
73
|
-
EOF
|
74
|
-
}
|
75
|
-
end
|
49
|
+
subject { core.diff('diff') }
|
50
|
+
it {
|
51
|
+
is_expected.to eq <<~EOF
|
52
|
+
---
|
53
|
+
-extra: diff1
|
54
|
+
-text: diff1
|
55
|
+
+extra: diff2
|
56
|
+
+text: diff2
|
57
|
+
EOF
|
58
|
+
}
|
76
59
|
end
|
77
60
|
|
78
61
|
describe '#except' do
|
79
|
-
subject { core.except({ a: :b, b: :c }
|
80
|
-
it { is_expected.to eq({ a: :b }) }
|
62
|
+
subject { core.except({ a: :b, b: :c }) }
|
63
|
+
it { is_expected.to eq({ a: :b, b: :c }) }
|
81
64
|
end
|
82
65
|
|
83
66
|
describe '#initialize' do
|
@@ -94,7 +77,7 @@ describe DatadogBackup::Core do
|
|
94
77
|
end
|
95
78
|
|
96
79
|
describe '#update' do
|
97
|
-
subject { core.
|
80
|
+
subject { core.update('abc-123-def', '{"a": "b"}') }
|
98
81
|
example 'it calls Dogapi::APIService.request' do
|
99
82
|
stub_const('Dogapi::APIService::API_VERSION', 'v1')
|
100
83
|
allow(core).to receive(:api_service).and_return(api_service_double)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe DatadogBackup::Dashboards do
|
6
|
+
let(:api_service_double) { double(Dogapi::APIService) }
|
6
7
|
let(:client_double) { double }
|
7
8
|
let(:tempdir) { Dir.mktmpdir }
|
8
9
|
let(:dashboards) do
|
@@ -59,8 +60,9 @@ describe DatadogBackup::Dashboards do
|
|
59
60
|
}
|
60
61
|
end
|
61
62
|
before(:example) do
|
62
|
-
allow(client_double).to receive(:
|
63
|
-
allow(
|
63
|
+
allow(client_double).to receive(:instance_variable_get).with(:@dashboard_service).and_return(api_service_double)
|
64
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/dashboard", nil, nil, false).and_return(all_boards)
|
65
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/dashboard/abc-123-def", nil, nil, false).and_return(example_dashboard)
|
64
66
|
end
|
65
67
|
|
66
68
|
describe '#backup' do
|
@@ -79,22 +81,34 @@ describe DatadogBackup::Dashboards do
|
|
79
81
|
describe '#all_boards' do
|
80
82
|
subject { dashboards.all_boards }
|
81
83
|
|
82
|
-
it 'calls get_all_boards' do
|
83
|
-
subject
|
84
|
-
expect(client_double).to have_received(:get_all_boards)
|
85
|
-
end
|
86
|
-
|
87
84
|
it { is_expected.to eq [dashboard_description] }
|
88
85
|
end
|
89
86
|
|
90
87
|
describe '#diff' do
|
91
88
|
it 'calls the api only once' do
|
92
89
|
dashboards.write_file('{"a":"b"}', dashboards.filename('abc-123-def'))
|
93
|
-
dashboards.diff('abc-123-def')
|
94
|
-
|
90
|
+
expect(dashboards.diff('abc-123-def')).to eq(<<~EOF
|
91
|
+
---
|
92
|
+
-description: example dashboard
|
93
|
+
-graphs:
|
94
|
+
-- definition:
|
95
|
+
- requests:
|
96
|
+
- - q: min:foo.bar{a:b}
|
97
|
+
- stacked: false
|
98
|
+
- viz: timeseries
|
99
|
+
- title: example graph
|
100
|
+
-title: example dashboard
|
101
|
+
+a: b
|
102
|
+
EOF
|
103
|
+
)
|
95
104
|
end
|
96
105
|
end
|
97
106
|
|
107
|
+
describe '#except' do
|
108
|
+
subject { dashboards.except({ :a => :b, 'modified_at' => :c, 'url' => :d }) }
|
109
|
+
it { is_expected.to eq({ a: :b }) }
|
110
|
+
end
|
111
|
+
|
98
112
|
describe '#get_by_id' do
|
99
113
|
subject { dashboards.get_by_id('abc-123-def') }
|
100
114
|
it { is_expected.to eq board_abc_123_def }
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe DatadogBackup::Monitors do
|
6
|
+
let(:api_service_double) { double(Dogapi::APIService) }
|
6
7
|
let(:client_double) { double }
|
7
8
|
let(:tempdir) { Dir.mktmpdir }
|
8
9
|
let(:monitors) do
|
@@ -47,19 +48,15 @@ describe DatadogBackup::Monitors do
|
|
47
48
|
monitor_description
|
48
49
|
]
|
49
50
|
end
|
51
|
+
|
50
52
|
before(:example) do
|
51
|
-
allow(client_double).to receive(:
|
52
|
-
allow(
|
53
|
+
allow(client_double).to receive(:instance_variable_get).with(:@monitor_svc).and_return(api_service_double)
|
54
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/monitor", nil, nil, false).and_return(all_monitors)
|
55
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, "/api/v1/dashboard/123455", nil, nil, false).and_return(example_monitor)
|
53
56
|
end
|
54
57
|
|
55
58
|
describe '#all_monitors' do
|
56
59
|
subject { monitors.all_monitors }
|
57
|
-
|
58
|
-
it 'calls get_all_monitors' do
|
59
|
-
subject
|
60
|
-
expect(client_double).to have_received(:get_all_monitors)
|
61
|
-
end
|
62
|
-
|
63
60
|
it { is_expected.to eq [monitor_description] }
|
64
61
|
end
|
65
62
|
|
@@ -76,10 +73,10 @@ describe DatadogBackup::Monitors do
|
|
76
73
|
end
|
77
74
|
end
|
78
75
|
|
79
|
-
describe '#diff' do
|
76
|
+
describe '#diff and #except' do
|
80
77
|
example 'it ignores `overall_state` and `overall_state_modified`' do
|
81
78
|
monitors.write_file(monitors.dump(monitor_description), monitors.filename(123_455))
|
82
|
-
allow(
|
79
|
+
allow(api_service_double).to receive(:request).and_return(
|
83
80
|
[
|
84
81
|
'200',
|
85
82
|
[
|
@@ -88,8 +85,8 @@ describe DatadogBackup::Monitors do
|
|
88
85
|
'message' => 'foo',
|
89
86
|
'id' => 123_455,
|
90
87
|
'name' => 'foo',
|
91
|
-
'overall_state' => '
|
92
|
-
'overall_state_modified' => '
|
88
|
+
'overall_state' => 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZ',
|
89
|
+
'overall_state_modified' => '9999-07-27T22:55:55+00:00'
|
93
90
|
}
|
94
91
|
]
|
95
92
|
]
|
data/spec/spec_helper.rb
CHANGED
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: 0.
|
4
|
+
version: 0.11.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:
|
12
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: amazing_print
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - '='
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 1.2.
|
20
|
+
version: 1.2.2
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - '='
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 1.2.
|
27
|
+
version: 1.2.2
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: concurrent-ruby
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,14 +87,14 @@ dependencies:
|
|
87
87
|
requirements:
|
88
88
|
- - '='
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 1.
|
90
|
+
version: 1.44.0
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - '='
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 1.
|
97
|
+
version: 1.44.0
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: bundler
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,11 +183,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
183
|
version: '0'
|
184
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
|
-
- - "
|
186
|
+
- - ">="
|
187
187
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
188
|
+
version: '0'
|
189
189
|
requirements: []
|
190
|
-
rubygems_version: 3.1.
|
190
|
+
rubygems_version: 3.1.4
|
191
191
|
signing_key:
|
192
192
|
specification_version: 4
|
193
193
|
summary: A utility to backup and restore Datadog accounts
|