datadog_backup 0.11.0 → 1.0.0.alpha.1

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: 9cfe289fb044024544f602c71cf219df872f7a624d5400cdfa38fca04a063cc4
4
- data.tar.gz: 1f646899a202ea0ddc5516135d9c9ffdb01f13e4b99a5f2a4d72222d9fb43169
3
+ metadata.gz: 5db8a5e804f30996a50247c24352e3fc1075971d141e37a2093987c510e9c9f1
4
+ data.tar.gz: 41c6f43d1c15c7e789aabe5a5b9bd34d45e5f5712d4ada557fb32edaeac4dd11
5
5
  SHA512:
6
- metadata.gz: a6fbcc8eb4385edd4ad17a3f4f29b26d15e33d1696337b7d9f7f74fb877627a1214f425f3aa2294206017757f77eb67b113da30a25b6c5446ecbe46bceb381a4
7
- data.tar.gz: f6576125ca22711b2f0102798f46cae7fd896cb006736a5c32ef75f76a720d663aa6970a87c67854461dafe0c64ebbcb489b1fc0eda6ac21750893420f479962
6
+ metadata.gz: f34c936e1a48773a4e0d600cfb23414c07b7197d7e72f9e1f7c3e1efd27c6b25b2ec9ab8643228b6b6d055f1b9c83762cf62e743418708ca8a02046405f256f7
7
+ data.tar.gz: e3f2a91bf80a2ea6c265766b55e07b01ac885a002a4be41f3f6dc7dc9574bdd394a158c1258887814b387290915f9843dc5a07759dc74d5c9d5c491c155b4ffe
@@ -1,3 +1,16 @@
1
+ # [1.0.0-alpha.1](https://github.com/scribd/datadog_backup/compare/v0.11.0...v1.0.0-alpha.1) (2021-01-17)
2
+
3
+
4
+ ### Features
5
+
6
+ * If resource doesn't exist in Datadog, the resource is recreated. ([95d9699](https://github.com/scribd/datadog_backup/commit/95d9699e3fe6a6ecae0d6690dce225680f1d6a8a))
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
+
1
14
  # [0.11.0](https://github.com/scribd/datadog_backup/compare/v0.10.3...v0.11.0) (2021-01-12)
2
15
 
3
16
 
@@ -55,7 +55,8 @@ def prereqs
55
55
  opts.on('--dashboards-only') do
56
56
  @options[:resources] = [DatadogBackup::Dashboards]
57
57
  end
58
- opts.on('--json', 'format backups as JSON instead of YAML. Does not impact `diffs` nor `restore`, but do not mix formats in the same backup-dir.') do
58
+ opts.on('--json',
59
+ 'format backups as JSON instead of YAML. Does not impact `diffs` nor `restore`, but do not mix formats in the same backup-dir.') do
59
60
  @options[:output_format] = :json
60
61
  end
61
62
  opts.on('--no-color', 'removes colored output from diff format') do
@@ -109,7 +109,7 @@ module DatadogBackup
109
109
  next unless diff
110
110
 
111
111
  if @options[:force_restore]
112
- definitive_resource_instance(id).update(id, definitive_resource_instance(id).load_from_file_by_id(id))
112
+ definitive_resource_instance(id).restore(id)
113
113
  else
114
114
  puts '--------------------------------------------------------------------------------'
115
115
  puts format_diff_output([id, diff])
@@ -120,7 +120,7 @@ module DatadogBackup
120
120
  exit
121
121
  when 'r'
122
122
  puts "Restoring #{id} to Datadog."
123
- definitive_resource_instance(id).update(id, definitive_resource_instance(id).load_from_file_by_id(id))
123
+ definitive_resource_instance(id).restore(id)
124
124
  when 'd'
125
125
  puts "Downloading #{id} from Datadog."
126
126
  definitive_resource_instance(id).get_and_write_file(id)
@@ -73,12 +73,38 @@ module DatadogBackup
73
73
  self.class.to_s.split(':').last.downcase
74
74
  end
75
75
 
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
83
+ end
84
+
76
85
  # Calls out to Datadog and checks for a '200' response
77
86
  def update(id, body)
78
- with_200 do
87
+ result = with_200 do
79
88
  api_service.request(Net::HTTP::Put, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, body, true)
80
89
  end
81
90
  logger.warn 'Successfully restored to datadog.'
91
+ result
92
+ end
93
+
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
+ get_and_write_file(new_id)
103
+ FileUtils.rm(find_file_by_id(id))
104
+ else
105
+ raise e.message
106
+ end
107
+ end
82
108
  end
83
109
 
84
110
  def with_200
@@ -94,9 +120,8 @@ module DatadogBackup
94
120
  sleep(0.1 * retries**5) # 0.1, 3.2, 24.3, 102.4 seconds per retry
95
121
  retry
96
122
  else
97
- raise "Request failed with error #{e.message}"
123
+ raise "Net::OpenTimeout: #{e.message}"
98
124
  end
99
125
  end
100
-
101
126
  end
102
127
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
- class Monitors < Core
4
+ class Monitors < Core
5
5
  def all_monitors
6
6
  @all_monitors ||= get_all
7
7
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
- VERSION = '0.11.0'
4
+ VERSION = '1.0.0.alpha.1'
5
5
  end
@@ -45,9 +45,12 @@ describe DatadogBackup::Cli do
45
45
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/deleted.json")
46
46
 
47
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
+ allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard', nil, nil,
49
+ false).and_return(all_boards)
50
+ allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard/stillthere', nil, nil,
51
+ false).and_return(['200', {}])
52
+ allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard/alsostillthere', nil,
53
+ nil, false).and_return(['200', {}])
51
54
  end
52
55
 
53
56
  it 'deletes the file locally as well' do
@@ -26,13 +26,13 @@ describe DatadogBackup::Core do
26
26
 
27
27
  describe '#with_200' do
28
28
  context 'with 200' do
29
- subject { core.with_200 {['200', { foo: :bar }]} }
29
+ subject { core.with_200 { ['200', { foo: :bar }] } }
30
30
 
31
31
  it { is_expected.to eq({ foo: :bar }) }
32
32
  end
33
33
 
34
34
  context 'with not 200' do
35
- subject { core.with_200 {['400', "Error message"]} }
35
+ subject { core.with_200 { ['400', 'Error message'] } }
36
36
 
37
37
  it 'raises an error' do
38
38
  expect { subject }.to raise_error(RuntimeError)
@@ -76,15 +76,92 @@ describe DatadogBackup::Core do
76
76
  it { is_expected.to eq 'core' }
77
77
  end
78
78
 
79
+ describe '#create' do
80
+ subject { core.create({ 'a' => 'b' }) }
81
+ example 'it calls Dogapi::APIService.request' do
82
+ stub_const('Dogapi::APIService::API_VERSION', 'v1')
83
+ allow(core).to receive(:api_service).and_return(api_service_double)
84
+ allow(core).to receive(:api_version).and_return('v1')
85
+ allow(core).to receive(:api_resource_name).and_return('dashboard')
86
+ expect(api_service_double).to receive(:request).with(Net::HTTP::Post, '/api/v1/dashboard', nil, { 'a' => 'b' },
87
+ true).and_return(['200', { 'id' => 'whatever-id-abc' }])
88
+ subject
89
+ end
90
+ end
91
+
79
92
  describe '#update' do
80
- subject { core.update('abc-123-def', '{"a": "b"}') }
93
+ subject { core.update('abc-123-def', { 'a' => 'b' }) }
81
94
  example 'it calls Dogapi::APIService.request' do
82
95
  stub_const('Dogapi::APIService::API_VERSION', 'v1')
83
96
  allow(core).to receive(:api_service).and_return(api_service_double)
84
97
  allow(core).to receive(:api_version).and_return('v1')
85
98
  allow(core).to receive(:api_resource_name).and_return('dashboard')
86
- expect(api_service_double).to receive(:request).with(Net::HTTP::Put, '/api/v1/dashboard/abc-123-def', nil, '{"a": "b"}', true).and_return(%w[200 Created])
99
+ expect(api_service_double).to receive(:request).with(Net::HTTP::Put, '/api/v1/dashboard/abc-123-def', nil,
100
+ { 'a' => 'b' }, true).and_return(['200',
101
+ { 'id' => 'whataver-man-thats-like-your-opinion' }])
87
102
  subject
88
103
  end
89
104
  end
105
+
106
+ describe '#restore' do
107
+ before(:each) do
108
+ allow(core).to receive(:api_service).and_return(api_service_double)
109
+ allow(core).to receive(:api_version).and_return('api-version-string')
110
+ allow(core).to receive(:api_resource_name).and_return('api-resource-name-string')
111
+ allow(api_service_double).to receive(:request).with(
112
+ Net::HTTP::Get,
113
+ '/api/api-version-string/api-resource-name-string/abc-123-def',
114
+ nil,
115
+ nil,
116
+ false
117
+ ).and_return(['200', { test: :ok }])
118
+ allow(api_service_double).to receive(:request).with(
119
+ Net::HTTP::Get,
120
+ '/api/api-version-string/api-resource-name-string/bad-123-id',
121
+ nil,
122
+ nil,
123
+ false
124
+ ).and_return(['404', { error: :blahblah_not_found }])
125
+ allow(core).to receive(:load_from_file_by_id).and_return({ 'load' => 'ok' })
126
+ end
127
+
128
+ context 'when id exists' do
129
+ subject { core.restore('abc-123-def') }
130
+ example 'it calls out to update' do
131
+ expect(core).to receive(:update).with('abc-123-def', { 'load' => 'ok' })
132
+ subject
133
+ end
134
+ end
135
+
136
+ context 'when id does not exist' do
137
+ before(:each) do
138
+ allow(api_service_double).to receive(:request).with(
139
+ Net::HTTP::Put,
140
+ '/api/api-version-string/api-resource-name-string/bad-123-id',
141
+ nil, { 'load' => 'ok' },
142
+ true
143
+ ).and_return(
144
+ ['404', { 'Error' => 'my not found' }]
145
+ )
146
+ allow(api_service_double).to receive(:request).with(
147
+ Net::HTTP::Post,
148
+ '/api/api-version-string/api-resource-name-string',
149
+ nil,
150
+ { 'load' => 'ok' },
151
+ true
152
+ ).and_return(
153
+ ['200', { 'id' => 'my-new-id' }]
154
+ )
155
+ end
156
+
157
+ subject { core.restore('bad-123-id') }
158
+ example 'it calls out to create then saves the new file and deletes the new file' do
159
+ expect(core).to receive(:create).with({ 'load' => 'ok' }).and_return({ 'id' => 'my-new-id' })
160
+ expect(core).to receive(:get_and_write_file).with('my-new-id')
161
+ allow(core).to receive(:find_file_by_id).with('bad-123-id').and_return('/path/to/bad-123-id.json')
162
+ expect(FileUtils).to receive(:rm).with('/path/to/bad-123-id.json')
163
+ subject
164
+ end
165
+ end
166
+ end
90
167
  end
@@ -61,8 +61,10 @@ describe DatadogBackup::Dashboards do
61
61
  end
62
62
  before(:example) do
63
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
+ allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard', nil, nil,
65
+ false).and_return(all_boards)
66
+ allow(api_service_double).to receive(:request).with(Net::HTTP::Get, '/api/v1/dashboard/abc-123-def', nil, nil,
67
+ false).and_return(example_dashboard)
66
68
  end
67
69
 
68
70
  describe '#backup' do
@@ -100,7 +102,7 @@ describe DatadogBackup::Dashboards do
100
102
  -title: example dashboard
101
103
  +a: b
102
104
  EOF
103
- )
105
+ )
104
106
  end
105
107
  end
106
108
 
@@ -51,8 +51,10 @@ describe DatadogBackup::Monitors do
51
51
 
52
52
  before(:example) do
53
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)
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)
56
58
  end
57
59
 
58
60
  describe '#all_monitors' do
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.11.0
4
+ version: 1.0.0.alpha.1
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: 2021-01-12 00:00:00.000000000 Z
12
+ date: 2021-01-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: amazing_print
@@ -183,9 +183,9 @@ 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: '0'
188
+ version: 1.3.1
189
189
  requirements: []
190
190
  rubygems_version: 3.1.4
191
191
  signing_key: