datadog_backup 0.11.0 → 1.0.0.alpha.1

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: 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: