datadog_backup 0.10.2 → 1.0.0.alpha.2
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/.gitignore +2 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +1 -0
- data/Guardfile +1 -1
- data/bin/datadog_backup +8 -1
- data/datadog_backup.gemspec +1 -1
- data/example/Gemfile +3 -1
- data/lib/datadog_backup/cli.rb +21 -18
- data/lib/datadog_backup/core.rb +53 -39
- data/lib/datadog_backup/dashboards.rb +4 -11
- data/lib/datadog_backup/local_filesystem.rb +7 -5
- data/lib/datadog_backup/monitors.rb +6 -10
- 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 +42 -22
- data/spec/datadog_backup/core_spec.rb +100 -38
- data/spec/datadog_backup/dashboards_spec.rb +30 -11
- data/spec/datadog_backup/local_filesystem_spec.rb +44 -24
- data/spec/datadog_backup/monitors_spec.rb +17 -13
- data/spec/datadog_backup_bin_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04e0cf7686b2efa66728d2bb5d3fd021847368a6522b3b3ba3cc9012a118e32f
|
4
|
+
data.tar.gz: 22643d6160be735c52f6bc25c134f250adae2ce9b6751c62ee04265d2082b9d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2293472fd1e18a59755e9e44ed1a39a17eb071e36de772c8ae146070138574f0726b016e9d0049cb8c8b8d625ce440a227ad5cf18a07a82ab77601580b96d01a
|
7
|
+
data.tar.gz: 583ff00c4a38005736f1bca85d80fc82eb6fbf8deb107044423ea2e7c3f87e05d82834f0051bf5fb7e5c2e476ea8c810292f93c392a3a1fe4e08a2be4327849e
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require: rubocop-rspec
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
# [1.0.0-alpha.2](https://github.com/scribd/datadog_backup/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2021-01-19)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* If resource doesn't exist in Datadog, the resource is recreated. ([f2f9e1f](https://github.com/scribd/datadog_backup/commit/f2f9e1f7b244eb3eeaaf121025769f9f327f4e1e))
|
7
|
+
|
8
|
+
|
9
|
+
### BREAKING CHANGES
|
10
|
+
|
11
|
+
* `datadog-backup` used to exit with an error if a resource
|
12
|
+
wasn't found in Datadog.
|
13
|
+
|
14
|
+
# [1.0.0-alpha.1](https://github.com/scribd/datadog_backup/compare/v0.11.0...v1.0.0-alpha.1) (2021-01-17)
|
15
|
+
|
16
|
+
|
17
|
+
### Features
|
18
|
+
|
19
|
+
* If resource doesn't exist in Datadog, the resource is recreated. ([95d9699](https://github.com/scribd/datadog_backup/commit/95d9699e3fe6a6ecae0d6690dce225680f1d6a8a))
|
20
|
+
|
21
|
+
|
22
|
+
### BREAKING CHANGES
|
23
|
+
|
24
|
+
* `datadog-backup` used to exit with an error if a resource
|
25
|
+
wasn't found in Datadog.
|
26
|
+
|
27
|
+
# [0.11.0](https://github.com/scribd/datadog_backup/compare/v0.10.3...v0.11.0) (2021-01-12)
|
28
|
+
|
29
|
+
|
30
|
+
### Features
|
31
|
+
|
32
|
+
* 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))
|
33
|
+
|
34
|
+
## [0.10.3](https://github.com/scribd/datadog_backup/compare/v0.10.2...v0.10.3) (2020-12-11)
|
35
|
+
|
36
|
+
|
37
|
+
### Performance Improvements
|
38
|
+
|
39
|
+
* coerce patch release ([bc86649](https://github.com/scribd/datadog_backup/commit/bc86649b874cd5be1da2f6bc0d1b1ecd0728676c))
|
40
|
+
|
1
41
|
## [0.10.2](https://github.com/scribd/datadog_backup/compare/v0.10.1...v0.10.2) (2020-11-03)
|
2
42
|
|
3
43
|
|
data/Gemfile
CHANGED
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
|
|
@@ -54,7 +55,10 @@ def prereqs
|
|
54
55
|
opts.on('--dashboards-only') do
|
55
56
|
@options[:resources] = [DatadogBackup::Dashboards]
|
56
57
|
end
|
57
|
-
opts.on(
|
58
|
+
opts.on(
|
59
|
+
'--json',
|
60
|
+
'format backups as JSON instead of YAML. Does not impact `diffs` nor `restore`, but do not mix formats in the same backup-dir.'
|
61
|
+
) do
|
58
62
|
@options[:output_format] = :json
|
59
63
|
end
|
60
64
|
opts.on('--no-color', 'removes colored output from diff format') do
|
@@ -63,6 +67,9 @@ def prereqs
|
|
63
67
|
opts.on('--diff-format FORMAT', 'one of `color`, `html_simple`, `html`') do |format|
|
64
68
|
@options[:diff_format] = format.to_sym
|
65
69
|
end
|
70
|
+
opts.on('--force-restore', 'force restore to Datadog') do
|
71
|
+
@options[:force_restore] = true
|
72
|
+
end
|
66
73
|
end
|
67
74
|
options.parse!
|
68
75
|
|
data/datadog_backup.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
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).restore(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).restore(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,46 @@ module DatadogBackup
|
|
80
73
|
self.class.to_s.split(':').last.downcase
|
81
74
|
end
|
82
75
|
|
83
|
-
|
84
|
-
|
76
|
+
# Calls out to Datadog and checks for a '200' response
|
77
|
+
def create(body)
|
78
|
+
result = with_200 do
|
79
|
+
api_service.request(Net::HTTP::Post, "/api/#{api_version}/#{api_resource_name}", nil, body, true)
|
80
|
+
end
|
81
|
+
logger.warn 'Successfully created in datadog.'
|
82
|
+
result
|
85
83
|
end
|
86
84
|
|
85
|
+
# Calls out to Datadog and checks for a '200' response
|
87
86
|
def update(id, body)
|
88
|
-
|
87
|
+
result = with_200 do
|
88
|
+
api_service.request(Net::HTTP::Put, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, body, true)
|
89
|
+
end
|
90
|
+
logger.warn 'Successfully restored to datadog.'
|
91
|
+
result
|
89
92
|
end
|
90
93
|
|
91
|
-
|
92
|
-
|
94
|
+
def restore(id)
|
95
|
+
body = load_from_file_by_id(id)
|
96
|
+
begin
|
97
|
+
update(id, body)
|
98
|
+
rescue RuntimeError => e
|
99
|
+
if e.message.include?('Request failed with error ["404"')
|
100
|
+
new_id = create(body).fetch('id')
|
101
|
+
|
102
|
+
FileUtils.rm(find_file_by_id(id))
|
103
|
+
get_and_write_file(new_id)
|
104
|
+
else
|
105
|
+
raise e.message
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def with_200
|
93
111
|
max_retries = 6
|
94
112
|
retries ||= 0
|
95
113
|
|
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."
|
114
|
+
response = yield
|
115
|
+
raise "Request failed with error #{response}" unless response[0] == '200'
|
102
116
|
|
103
117
|
response[1]
|
104
118
|
rescue ::Net::OpenTimeout => e
|
@@ -106,7 +120,7 @@ module DatadogBackup
|
|
106
120
|
sleep(0.1 * retries**5) # 0.1, 3.2, 24.3, 102.4 seconds per retry
|
107
121
|
retry
|
108
122
|
else
|
109
|
-
raise "
|
123
|
+
raise "Net::OpenTimeout: #{e.message}"
|
110
124
|
end
|
111
125
|
end
|
112
126
|
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'
|
@@ -2,11 +2,8 @@
|
|
2
2
|
|
3
3
|
module DatadogBackup
|
4
4
|
class Monitors < Core
|
5
|
-
API_SERVICE_NAME = :@monitor_svc
|
6
|
-
BANLIST = %w[overall_state overall_state_modified matching_downtimes modified]
|
7
|
-
|
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
|
@@ -18,10 +19,10 @@ describe DatadogBackup::Cli do
|
|
18
19
|
resources: [DatadogBackup::Dashboards]
|
19
20
|
}
|
20
21
|
end
|
21
|
-
let(:cli) {
|
22
|
+
let(:cli) { described_class.new(options) }
|
22
23
|
let(:dashboards) { DatadogBackup::Dashboards.new(options) }
|
23
24
|
|
24
|
-
before
|
25
|
+
before do
|
25
26
|
allow(cli).to receive(:resource_instances).and_return([dashboards])
|
26
27
|
end
|
27
28
|
|
@@ -38,13 +39,28 @@ describe DatadogBackup::Cli do
|
|
38
39
|
}
|
39
40
|
]
|
40
41
|
end
|
41
|
-
|
42
|
+
|
43
|
+
before do
|
42
44
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/stillthere.json")
|
43
45
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/alsostillthere.json")
|
44
46
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/deleted.json")
|
45
47
|
|
46
|
-
allow(client_double).to receive(:
|
47
|
-
allow(
|
48
|
+
allow(client_double).to receive(:instance_variable_get).with(:@dashboard_service).and_return(api_service_double)
|
49
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get,
|
50
|
+
'/api/v1/dashboard',
|
51
|
+
nil,
|
52
|
+
nil,
|
53
|
+
false).and_return(all_boards)
|
54
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get,
|
55
|
+
'/api/v1/dashboard/stillthere',
|
56
|
+
nil,
|
57
|
+
nil,
|
58
|
+
false).and_return(['200', {}])
|
59
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get,
|
60
|
+
'/api/v1/dashboard/alsostillthere',
|
61
|
+
nil,
|
62
|
+
nil,
|
63
|
+
false).and_return(['200', {}])
|
48
64
|
end
|
49
65
|
|
50
66
|
it 'deletes the file locally as well' do
|
@@ -55,16 +71,18 @@ describe DatadogBackup::Cli do
|
|
55
71
|
end
|
56
72
|
|
57
73
|
describe '#diffs' do
|
58
|
-
|
74
|
+
subject { cli.diffs }
|
75
|
+
|
76
|
+
before do
|
59
77
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs1.json")
|
60
78
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs2.json")
|
61
79
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs3.json")
|
62
80
|
allow(dashboards).to receive(:get_by_id).and_return({ 'text' => 'diff2' })
|
63
81
|
allow(cli).to receive(:initialize_client).and_return(client_double)
|
64
82
|
end
|
65
|
-
|
83
|
+
|
66
84
|
it {
|
67
|
-
|
85
|
+
expect(subject).to include(
|
68
86
|
" ---\n id: diffs1\n ---\n-text: diff2\n+text: diff\n",
|
69
87
|
" ---\n id: diffs3\n ---\n-text: diff2\n+text: diff\n",
|
70
88
|
" ---\n id: diffs2\n ---\n-text: diff2\n+text: diff\n"
|
@@ -73,44 +91,46 @@ describe DatadogBackup::Cli do
|
|
73
91
|
end
|
74
92
|
|
75
93
|
describe '#restore' do
|
76
|
-
|
94
|
+
subject { cli.restore }
|
95
|
+
|
96
|
+
before do
|
77
97
|
dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs1.json")
|
78
98
|
allow(dashboards).to receive(:get_by_id).and_return({ 'text' => 'diff2' })
|
79
99
|
allow(cli).to receive(:initialize_client).and_return(client_double)
|
80
100
|
end
|
81
101
|
|
82
|
-
subject { cli.restore }
|
83
|
-
|
84
102
|
example 'starts interactive restore' do
|
85
103
|
allow($stdin).to receive(:gets).and_return('q')
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
104
|
+
|
105
|
+
expect { subject }.to(
|
106
|
+
output(/\(r\)estore to Datadog, overwrite local changes and \(d\)ownload, \(s\)kip, or \(q\)uit\?/).to_stdout
|
107
|
+
.and(raise_error(SystemExit))
|
108
|
+
)
|
92
109
|
end
|
93
110
|
|
94
111
|
example 'restore' do
|
95
112
|
allow($stdin).to receive(:gets).and_return('r')
|
96
|
-
expect(dashboards).to receive(:
|
113
|
+
expect(dashboards).to receive(:update).with('diffs1', { 'text' => 'diff' })
|
97
114
|
subject
|
98
115
|
end
|
116
|
+
|
99
117
|
example 'download' do
|
100
118
|
allow($stdin).to receive(:gets).and_return('d')
|
101
119
|
expect(dashboards).to receive(:write_file).with(%({\n "text": "diff2"\n}), "#{tempdir}/dashboards/diffs1.json")
|
102
120
|
subject
|
103
121
|
end
|
122
|
+
|
104
123
|
example 'skip' do
|
105
124
|
allow($stdin).to receive(:gets).and_return('s')
|
106
|
-
expect(dashboards).
|
107
|
-
expect(dashboards).
|
125
|
+
expect(dashboards).not_to receive(:write_file)
|
126
|
+
expect(dashboards).not_to receive(:update)
|
108
127
|
subject
|
109
128
|
end
|
129
|
+
|
110
130
|
example 'quit' do
|
111
131
|
allow($stdin).to receive(:gets).and_return('q')
|
112
|
-
expect(dashboards).
|
113
|
-
expect(dashboards).
|
132
|
+
expect(dashboards).not_to receive(:write_file)
|
133
|
+
expect(dashboards).not_to receive(:update)
|
114
134
|
expect { subject }.to raise_error(SystemExit)
|
115
135
|
end
|
116
136
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe DatadogBackup::Core do
|
@@ -5,7 +7,7 @@ describe DatadogBackup::Core do
|
|
5
7
|
let(:client_double) { double }
|
6
8
|
let(:tempdir) { Dir.mktmpdir }
|
7
9
|
let(:core) do
|
8
|
-
|
10
|
+
described_class.new(
|
9
11
|
action: 'backup',
|
10
12
|
api_service: api_service_double,
|
11
13
|
client: client_double,
|
@@ -19,24 +21,19 @@ describe DatadogBackup::Core do
|
|
19
21
|
|
20
22
|
describe '#client' do
|
21
23
|
subject { core.client }
|
24
|
+
|
22
25
|
it { is_expected.to eq client_double }
|
23
26
|
end
|
24
27
|
|
25
|
-
describe '#
|
26
|
-
subject { core.client_with_200(:get_all_boards) }
|
27
|
-
|
28
|
+
describe '#with_200' do
|
28
29
|
context 'with 200' do
|
29
|
-
|
30
|
-
allow(client_double).to receive(:get_all_boards).and_return(['200', { foo: :bar }])
|
31
|
-
end
|
30
|
+
subject { core.with_200 { ['200', { foo: :bar }] } }
|
32
31
|
|
33
32
|
it { is_expected.to eq({ foo: :bar }) }
|
34
33
|
end
|
35
34
|
|
36
35
|
context 'with not 200' do
|
37
|
-
|
38
|
-
allow(client_double).to receive(:get_all_boards).and_return(['401', {}])
|
39
|
-
end
|
36
|
+
subject { core.with_200 { ['400', 'Error message'] } }
|
40
37
|
|
41
38
|
it 'raises an error' do
|
42
39
|
expect { subject }.to raise_error(RuntimeError)
|
@@ -45,43 +42,33 @@ describe DatadogBackup::Core do
|
|
45
42
|
end
|
46
43
|
|
47
44
|
describe '#diff' do
|
48
|
-
|
45
|
+
subject { core.diff('diff') }
|
46
|
+
|
47
|
+
before do
|
49
48
|
allow(core).to receive(:get_by_id).and_return({ 'text' => 'diff1', 'extra' => 'diff1' })
|
50
49
|
core.write_file('{"text": "diff2", "extra": "diff2"}', "#{tempdir}/core/diff.json")
|
51
50
|
end
|
52
51
|
|
53
|
-
|
54
|
-
subject
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
EOF
|
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
|
52
|
+
it {
|
53
|
+
expect(subject).to eq <<~EOF
|
54
|
+
---
|
55
|
+
-extra: diff1
|
56
|
+
-text: diff1
|
57
|
+
+extra: diff2
|
58
|
+
+text: diff2
|
59
|
+
EOF
|
60
|
+
}
|
76
61
|
end
|
77
62
|
|
78
63
|
describe '#except' do
|
79
|
-
subject { core.except({ a: :b, b: :c }
|
80
|
-
|
64
|
+
subject { core.except({ a: :b, b: :c }) }
|
65
|
+
|
66
|
+
it { is_expected.to eq({ a: :b, b: :c }) }
|
81
67
|
end
|
82
68
|
|
83
69
|
describe '#initialize' do
|
84
70
|
subject { core }
|
71
|
+
|
85
72
|
it 'makes the subdirectories' do
|
86
73
|
expect(FileUtils).to receive(:mkdir_p).with("#{tempdir}/core")
|
87
74
|
subject
|
@@ -90,18 +77,93 @@ describe DatadogBackup::Core do
|
|
90
77
|
|
91
78
|
describe '#myclass' do
|
92
79
|
subject { core.myclass }
|
80
|
+
|
93
81
|
it { is_expected.to eq 'core' }
|
94
82
|
end
|
95
83
|
|
84
|
+
describe '#create' do
|
85
|
+
subject { core.create({ 'a' => 'b' }) }
|
86
|
+
|
87
|
+
example 'it calls Dogapi::APIService.request' do
|
88
|
+
stub_const('Dogapi::APIService::API_VERSION', 'v1')
|
89
|
+
allow(core).to receive(:api_service).and_return(api_service_double)
|
90
|
+
allow(core).to receive(:api_version).and_return('v1')
|
91
|
+
allow(core).to receive(:api_resource_name).and_return('dashboard')
|
92
|
+
expect(api_service_double).to receive(:request).with(Net::HTTP::Post,
|
93
|
+
'/api/v1/dashboard',
|
94
|
+
nil,
|
95
|
+
{ 'a' => 'b' },
|
96
|
+
true).and_return(['200', { 'id' => 'whatever-id-abc' }])
|
97
|
+
subject
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
96
101
|
describe '#update' do
|
97
|
-
subject { core.
|
102
|
+
subject { core.update('abc-123-def', { 'a' => 'b' }) }
|
103
|
+
|
98
104
|
example 'it calls Dogapi::APIService.request' do
|
99
105
|
stub_const('Dogapi::APIService::API_VERSION', 'v1')
|
100
106
|
allow(core).to receive(:api_service).and_return(api_service_double)
|
101
107
|
allow(core).to receive(:api_version).and_return('v1')
|
102
108
|
allow(core).to receive(:api_resource_name).and_return('dashboard')
|
103
|
-
expect(api_service_double).to receive(:request).with(Net::HTTP::Put,
|
109
|
+
expect(api_service_double).to receive(:request).with(Net::HTTP::Put,
|
110
|
+
'/api/v1/dashboard/abc-123-def',
|
111
|
+
nil,
|
112
|
+
{ 'a' => 'b' },
|
113
|
+
true).and_return(['200', { 'id' => 'whatever-id-abc' }])
|
104
114
|
subject
|
105
115
|
end
|
106
116
|
end
|
117
|
+
|
118
|
+
describe '#restore' do
|
119
|
+
before do
|
120
|
+
allow(core).to receive(:api_service).and_return(api_service_double)
|
121
|
+
allow(core).to receive(:api_version).and_return('api-version-string')
|
122
|
+
allow(core).to receive(:api_resource_name).and_return('api-resource-name-string')
|
123
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get,
|
124
|
+
'/api/api-version-string/api-resource-name-string/abc-123-def',
|
125
|
+
nil,
|
126
|
+
nil,
|
127
|
+
false).and_return(['200', { test: :ok }])
|
128
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get,
|
129
|
+
'/api/api-version-string/api-resource-name-string/bad-123-id',
|
130
|
+
nil,
|
131
|
+
nil,
|
132
|
+
false).and_return(['404', { error: :blahblah_not_found }])
|
133
|
+
allow(core).to receive(:load_from_file_by_id).and_return({ 'load' => 'ok' })
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'when id exists' do
|
137
|
+
subject { core.restore('abc-123-def') }
|
138
|
+
|
139
|
+
example 'it calls out to update' do
|
140
|
+
expect(core).to receive(:update).with('abc-123-def', { 'load' => 'ok' })
|
141
|
+
subject
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when id does not exist' do
|
146
|
+
subject { core.restore('bad-123-id') }
|
147
|
+
|
148
|
+
before do
|
149
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Put,
|
150
|
+
'/api/api-version-string/api-resource-name-string/bad-123-id',
|
151
|
+
nil, { 'load' => 'ok' },
|
152
|
+
true).and_return(['404', { 'Error' => 'my not found' }])
|
153
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Post,
|
154
|
+
'/api/api-version-string/api-resource-name-string',
|
155
|
+
nil,
|
156
|
+
{ 'load' => 'ok' },
|
157
|
+
true).and_return(['200', { 'id' => 'my-new-id' }])
|
158
|
+
end
|
159
|
+
|
160
|
+
example 'it calls out to create then saves the new file and deletes the new file' do
|
161
|
+
expect(core).to receive(:create).with({ 'load' => 'ok' }).and_return({ 'id' => 'my-new-id' })
|
162
|
+
expect(core).to receive(:get_and_write_file).with('my-new-id')
|
163
|
+
allow(core).to receive(:find_file_by_id).with('bad-123-id').and_return('/path/to/bad-123-id.json')
|
164
|
+
expect(FileUtils).to receive(:rm).with('/path/to/bad-123-id.json')
|
165
|
+
subject
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
107
169
|
end
|
@@ -3,10 +3,11 @@
|
|
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
|
9
|
-
|
10
|
+
described_class.new(
|
10
11
|
action: 'backup',
|
11
12
|
client: client_double,
|
12
13
|
backup_dir: tempdir,
|
@@ -58,9 +59,13 @@ describe DatadogBackup::Dashboards do
|
|
58
59
|
'title' => 'example dashboard'
|
59
60
|
}
|
60
61
|
end
|
61
|
-
|
62
|
-
|
63
|
-
allow(client_double).to receive(:
|
62
|
+
|
63
|
+
before do
|
64
|
+
allow(client_double).to receive(:instance_variable_get).with(:@dashboard_service).and_return(api_service_double)
|
65
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard', nil, nil,
|
66
|
+
false).and_return(all_boards)
|
67
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard/abc-123-def', nil, nil,
|
68
|
+
false).and_return(example_dashboard)
|
64
69
|
end
|
65
70
|
|
66
71
|
describe '#backup' do
|
@@ -79,24 +84,38 @@ describe DatadogBackup::Dashboards do
|
|
79
84
|
describe '#all_boards' do
|
80
85
|
subject { dashboards.all_boards }
|
81
86
|
|
82
|
-
it 'calls get_all_boards' do
|
83
|
-
subject
|
84
|
-
expect(client_double).to have_received(:get_all_boards)
|
85
|
-
end
|
86
|
-
|
87
87
|
it { is_expected.to eq [dashboard_description] }
|
88
88
|
end
|
89
89
|
|
90
90
|
describe '#diff' do
|
91
91
|
it 'calls the api only once' do
|
92
92
|
dashboards.write_file('{"a":"b"}', dashboards.filename('abc-123-def'))
|
93
|
-
dashboards.diff('abc-123-def')
|
94
|
-
|
93
|
+
expect(dashboards.diff('abc-123-def')).to eq(<<~EOF
|
94
|
+
---
|
95
|
+
-description: example dashboard
|
96
|
+
-graphs:
|
97
|
+
-- definition:
|
98
|
+
- requests:
|
99
|
+
- - q: min:foo.bar{a:b}
|
100
|
+
- stacked: false
|
101
|
+
- viz: timeseries
|
102
|
+
- title: example graph
|
103
|
+
-title: example dashboard
|
104
|
+
+a: b
|
105
|
+
EOF
|
106
|
+
)
|
95
107
|
end
|
96
108
|
end
|
97
109
|
|
110
|
+
describe '#except' do
|
111
|
+
subject { dashboards.except({ :a => :b, 'modified_at' => :c, 'url' => :d }) }
|
112
|
+
|
113
|
+
it { is_expected.to eq({ a: :b }) }
|
114
|
+
end
|
115
|
+
|
98
116
|
describe '#get_by_id' do
|
99
117
|
subject { dashboards.get_by_id('abc-123-def') }
|
118
|
+
|
100
119
|
it { is_expected.to eq board_abc_123_def }
|
101
120
|
end
|
102
121
|
end
|
@@ -27,55 +27,61 @@ describe DatadogBackup::LocalFilesystem do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
describe '#all_files' do
|
30
|
-
|
30
|
+
subject { core.all_files }
|
31
|
+
|
32
|
+
before do
|
31
33
|
File.new("#{tempdir}/all_files.json", 'w')
|
32
34
|
end
|
33
35
|
|
34
|
-
after
|
36
|
+
after do
|
35
37
|
FileUtils.rm "#{tempdir}/all_files.json"
|
36
38
|
end
|
37
39
|
|
38
|
-
subject { core.all_files }
|
39
40
|
it { is_expected.to eq(["#{tempdir}/all_files.json"]) }
|
40
41
|
end
|
41
42
|
|
42
43
|
describe '#all_file_ids_for_selected_resources' do
|
43
|
-
|
44
|
+
subject { core.all_file_ids_for_selected_resources }
|
45
|
+
|
46
|
+
before do
|
44
47
|
Dir.mkdir("#{tempdir}/dashboards")
|
45
48
|
Dir.mkdir("#{tempdir}/monitors")
|
46
49
|
File.new("#{tempdir}/dashboards/all_files.json", 'w')
|
47
50
|
File.new("#{tempdir}/monitors/12345.json", 'w')
|
48
51
|
end
|
49
52
|
|
50
|
-
after
|
53
|
+
after do
|
51
54
|
FileUtils.rm "#{tempdir}/dashboards/all_files.json"
|
52
55
|
FileUtils.rm "#{tempdir}/monitors/12345.json"
|
53
56
|
end
|
54
57
|
|
55
|
-
subject { core.all_file_ids_for_selected_resources }
|
56
58
|
it { is_expected.to eq(['all_files']) }
|
57
59
|
end
|
58
60
|
|
59
61
|
describe '#class_from_id' do
|
60
|
-
|
62
|
+
subject { core.class_from_id('abc-123-def') }
|
63
|
+
|
64
|
+
before do
|
61
65
|
core.write_file('abc', "#{tempdir}/core/abc-123-def.json")
|
62
66
|
end
|
63
67
|
|
64
|
-
after
|
68
|
+
after do
|
65
69
|
FileUtils.rm "#{tempdir}/core/abc-123-def.json"
|
66
70
|
end
|
67
|
-
|
71
|
+
|
68
72
|
it { is_expected.to eq DatadogBackup::Core }
|
69
73
|
end
|
70
74
|
|
71
75
|
describe '#dump' do
|
72
76
|
context ':json' do
|
73
77
|
subject { core.dump({ a: :b }) }
|
78
|
+
|
74
79
|
it { is_expected.to eq(%({\n "a": "b"\n})) }
|
75
80
|
end
|
76
81
|
|
77
82
|
context ':yaml' do
|
78
83
|
subject { core_yaml.dump({ 'a' => 'b' }) }
|
84
|
+
|
79
85
|
it { is_expected.to eq(%(---\na: b\n)) }
|
80
86
|
end
|
81
87
|
end
|
@@ -83,80 +89,94 @@ describe DatadogBackup::LocalFilesystem do
|
|
83
89
|
describe '#filename' do
|
84
90
|
context ':json' do
|
85
91
|
subject { core.filename('abc-123-def') }
|
92
|
+
|
86
93
|
it { is_expected.to eq("#{tempdir}/core/abc-123-def.json") }
|
87
94
|
end
|
88
95
|
|
89
96
|
context ':yaml' do
|
90
97
|
subject { core_yaml.filename('abc-123-def') }
|
98
|
+
|
91
99
|
it { is_expected.to eq("#{tempdir}/core/abc-123-def.yaml") }
|
92
100
|
end
|
93
101
|
end
|
94
102
|
|
95
103
|
describe '#file_type' do
|
96
|
-
|
104
|
+
subject { core.file_type("#{tempdir}/file_type.json") }
|
105
|
+
|
106
|
+
before do
|
97
107
|
File.new("#{tempdir}/file_type.json", 'w')
|
98
108
|
end
|
99
109
|
|
100
|
-
after
|
110
|
+
after do
|
101
111
|
FileUtils.rm "#{tempdir}/file_type.json"
|
102
112
|
end
|
103
113
|
|
104
|
-
subject { core.file_type("#{tempdir}/file_type.json") }
|
105
114
|
it { is_expected.to eq :json }
|
106
115
|
end
|
107
116
|
|
108
117
|
describe '#find_file_by_id' do
|
109
|
-
|
118
|
+
subject { core.find_file_by_id('find_file') }
|
119
|
+
|
120
|
+
before do
|
110
121
|
File.new("#{tempdir}/find_file.json", 'w')
|
111
122
|
end
|
112
123
|
|
113
|
-
after
|
124
|
+
after do
|
114
125
|
FileUtils.rm "#{tempdir}/find_file.json"
|
115
126
|
end
|
116
127
|
|
117
|
-
subject { core.find_file_by_id('find_file') }
|
118
128
|
it { is_expected.to eq "#{tempdir}/find_file.json" }
|
119
129
|
end
|
120
130
|
|
121
131
|
describe '#load_from_file' do
|
122
132
|
context ':json' do
|
123
133
|
subject { core.load_from_file(%({\n "a": "b"\n}), :json) }
|
134
|
+
|
124
135
|
it { is_expected.to eq('a' => 'b') }
|
125
136
|
end
|
126
137
|
|
127
138
|
context ':yaml' do
|
128
139
|
subject { core.load_from_file(%(---\na: b\n), :yaml) }
|
140
|
+
|
129
141
|
it { is_expected.to eq('a' => 'b') }
|
130
142
|
end
|
131
143
|
end
|
132
144
|
|
133
145
|
describe '#load_from_file_by_id' do
|
134
146
|
context 'written in json read in yaml mode' do
|
135
|
-
before(:example) { core.write_file(%({"a": "b"}), "#{tempdir}/core/abc-123-def.json") }
|
136
|
-
after(:example) { FileUtils.rm "#{tempdir}/core/abc-123-def.json" }
|
137
|
-
|
138
147
|
subject { core_yaml.load_from_file_by_id('abc-123-def') }
|
148
|
+
|
149
|
+
before { core.write_file(%({"a": "b"}), "#{tempdir}/core/abc-123-def.json") }
|
150
|
+
|
151
|
+
after { FileUtils.rm "#{tempdir}/core/abc-123-def.json" }
|
152
|
+
|
139
153
|
it { is_expected.to eq('a' => 'b') }
|
140
154
|
end
|
141
|
-
context 'written in yaml read in json mode' do
|
142
|
-
before(:example) { core.write_file(%(---\na: b), "#{tempdir}/core/abc-123-def.yaml") }
|
143
|
-
after(:example) { FileUtils.rm "#{tempdir}/core/abc-123-def.yaml" }
|
144
155
|
|
156
|
+
context 'written in yaml read in json mode' do
|
145
157
|
subject { core.load_from_file_by_id('abc-123-def') }
|
158
|
+
|
159
|
+
before { core.write_file(%(---\na: b), "#{tempdir}/core/abc-123-def.yaml") }
|
160
|
+
|
161
|
+
after { FileUtils.rm "#{tempdir}/core/abc-123-def.yaml" }
|
162
|
+
|
146
163
|
it { is_expected.to eq('a' => 'b') }
|
147
164
|
end
|
148
165
|
|
149
166
|
context 'Integer as parameter' do
|
150
|
-
before(:example) { core.write_file(%(---\na: b), "#{tempdir}/core/12345.yaml") }
|
151
|
-
after(:example) { FileUtils.rm "#{tempdir}/core/12345.yaml" }
|
152
|
-
|
153
167
|
subject { core.load_from_file_by_id(12_345) }
|
168
|
+
|
169
|
+
before { core.write_file(%(---\na: b), "#{tempdir}/core/12345.yaml") }
|
170
|
+
|
171
|
+
after { FileUtils.rm "#{tempdir}/core/12345.yaml" }
|
172
|
+
|
154
173
|
it { is_expected.to eq('a' => 'b') }
|
155
174
|
end
|
156
175
|
end
|
157
176
|
|
158
177
|
describe '#write_file' do
|
159
178
|
subject { core.write_file('abc123', "#{tempdir}/core/abc-123-def.json") }
|
179
|
+
|
160
180
|
let(:file_like_object) { double }
|
161
181
|
|
162
182
|
it 'writes a file to abc-123-def.json' do
|
@@ -3,10 +3,11 @@
|
|
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
|
9
|
-
|
10
|
+
described_class.new(
|
10
11
|
action: 'backup',
|
11
12
|
client: client_double,
|
12
13
|
backup_dir: tempdir,
|
@@ -47,19 +48,18 @@ describe DatadogBackup::Monitors do
|
|
47
48
|
monitor_description
|
48
49
|
]
|
49
50
|
end
|
50
|
-
|
51
|
-
|
52
|
-
allow(client_double).to receive(:
|
51
|
+
|
52
|
+
before do
|
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,
|
55
|
+
false).and_return(all_monitors)
|
56
|
+
allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard/123455', nil, nil,
|
57
|
+
false).and_return(example_monitor)
|
53
58
|
end
|
54
59
|
|
55
60
|
describe '#all_monitors' do
|
56
61
|
subject { monitors.all_monitors }
|
57
62
|
|
58
|
-
it 'calls get_all_monitors' do
|
59
|
-
subject
|
60
|
-
expect(client_double).to have_received(:get_all_monitors)
|
61
|
-
end
|
62
|
-
|
63
63
|
it { is_expected.to eq [monitor_description] }
|
64
64
|
end
|
65
65
|
|
@@ -76,10 +76,10 @@ describe DatadogBackup::Monitors do
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
describe '#diff' do
|
79
|
+
describe '#diff and #except' do
|
80
80
|
example 'it ignores `overall_state` and `overall_state_modified`' do
|
81
81
|
monitors.write_file(monitors.dump(monitor_description), monitors.filename(123_455))
|
82
|
-
allow(
|
82
|
+
allow(api_service_double).to receive(:request).and_return(
|
83
83
|
[
|
84
84
|
'200',
|
85
85
|
[
|
@@ -88,8 +88,8 @@ describe DatadogBackup::Monitors do
|
|
88
88
|
'message' => 'foo',
|
89
89
|
'id' => 123_455,
|
90
90
|
'name' => 'foo',
|
91
|
-
'overall_state' => '
|
92
|
-
'overall_state_modified' => '
|
91
|
+
'overall_state' => 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZ',
|
92
|
+
'overall_state_modified' => '9999-07-27T22:55:55+00:00'
|
93
93
|
}
|
94
94
|
]
|
95
95
|
]
|
@@ -103,16 +103,20 @@ describe DatadogBackup::Monitors do
|
|
103
103
|
|
104
104
|
describe '#filename' do
|
105
105
|
subject { monitors.filename(123_455) }
|
106
|
+
|
106
107
|
it { is_expected.to eq("#{tempdir}/monitors/123455.json") }
|
107
108
|
end
|
108
109
|
|
109
110
|
describe '#get_by_id' do
|
110
111
|
context 'Integer' do
|
111
112
|
subject { monitors.get_by_id(123_455) }
|
113
|
+
|
112
114
|
it { is_expected.to eq monitor_description }
|
113
115
|
end
|
116
|
+
|
114
117
|
context 'String' do
|
115
118
|
subject { monitors.get_by_id('123455') }
|
119
|
+
|
116
120
|
it { is_expected.to eq monitor_description }
|
117
121
|
end
|
118
122
|
end
|
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: 1.0.0.alpha.2
|
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-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: amazing_print
|
@@ -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
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- ".github/dependabot.yml"
|
136
136
|
- ".github/workflows/rspec_and_release.yml"
|
137
137
|
- ".gitignore"
|
138
|
+
- ".rubocop.yml"
|
138
139
|
- CHANGELOG.md
|
139
140
|
- CODE_OF_CONDUCT.md
|
140
141
|
- Gemfile
|
@@ -183,9 +184,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
184
|
version: '0'
|
184
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
186
|
requirements:
|
186
|
-
- - "
|
187
|
+
- - ">"
|
187
188
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
189
|
+
version: 1.3.1
|
189
190
|
requirements: []
|
190
191
|
rubygems_version: 3.1.4
|
191
192
|
signing_key:
|