datadog_backup 0.11.0.alpha.1 → 1.0.1.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: 3894769e0beaf7ceec6916b814ee5178cea0676e1f449c0871e290f7e15b1186
4
- data.tar.gz: 27f904e921aed4cb494ca269f4537ce3c6ca8547427d6d8399448f6d219a085a
3
+ metadata.gz: 24038b9209cab6ebe03f9f7f4d90aa102824a415fb80bc043c7e04694b0ea52c
4
+ data.tar.gz: 4372fa6964f6d08285b16d38ba5d934c37d12ac7cb7328af22f56b1ade996f7b
5
5
  SHA512:
6
- metadata.gz: 0ac749ca73299279b3997ab4b144938e6b49f267f432e96b40b8afcc88546ba24fd841aa770778bf6b82953be10f534db1d7842a46a05b8addfe91961fa5c59e
7
- data.tar.gz: 4bbece6af403febc4ef2d0f8f269fd176efb25da0684e486576d14d50d4d3640fc2ac1aaed37b50221d665c44dd993daef5342d6158c74ec674194665316e694
6
+ metadata.gz: 92f24e24cb04743e02b65a12cd1a500b2398ed5323cb482ce0a32538513100a7d451a23d71979c7fda14c4ef7b8f1466290fc571a416e9dec4b5f1847c09d015
7
+ data.tar.gz: 1c84a2c4390e66ba48ff593638fffcaba9a94442c7a1775ec073380b30160ab5304eb4ad58d5265f1d3983abc331732849a64df28f271d509a3a347c99f9b652
@@ -9,6 +9,10 @@ updates:
9
9
  directory: "/" # Location of package manifests
10
10
  schedule:
11
11
  interval: "daily"
12
+ commit_message:
13
+ prefix: "deps"
14
+ prefix_development: "chore"
15
+ include_scope: true
12
16
  - package-ecosystem: "github-actions"
13
17
  directory: "/" # Location of package manifests
14
18
  schedule:
@@ -8,35 +8,30 @@ on:
8
8
  jobs:
9
9
  rspec:
10
10
  runs-on: ubuntu-latest
11
-
12
11
  steps:
13
12
  - uses: actions/checkout@v2
14
13
  - name: Set up Ruby 2.7.2
15
- uses: actions/setup-ruby@v1.1.2
14
+ uses: ruby/setup-ruby@v1
16
15
  with:
17
- ruby-version: 2.7.2
16
+ ruby-version: 2.7
17
+ bundler-cache: true
18
18
  - name: Test with Rspec
19
19
  run: |
20
- gem install --no-document bundler
21
- bundle install --jobs 4 --retry 3
22
20
  bundle exec rspec --format documentation
23
21
  release:
24
22
  if: github.event_name == 'push'
25
23
  needs: rspec
26
24
  runs-on: ubuntu-latest
27
-
25
+ env:
26
+ BUNDLE_WITHOUT: "development:test"
27
+ BUNDLE_DEPLOYMENT: "true"
28
28
  steps:
29
29
  - uses: actions/checkout@v2
30
30
  - name: Set up Ruby 2.7.2
31
- uses: actions/setup-ruby@v1.1.2
31
+ uses: ruby/setup-ruby@v1
32
32
  with:
33
- ruby-version: 2.7.2
34
- - name: Build with bundler
35
- run: |
36
- gem install --no-document bundler
37
- bundle config set deployment 'true'
38
- bundle config set without 'development test'
39
- bundle install --jobs 4 --retry 3
33
+ ruby-version: 2.7
34
+ bundler-cache: true
40
35
  - name: Zip
41
36
  run : |
42
37
  zip -r datadog_backup.zip ./*
data/.rubocop.yml ADDED
@@ -0,0 +1 @@
1
+ require: rubocop-rspec
data/CHANGELOG.md CHANGED
@@ -1,9 +1,36 @@
1
- # [0.11.0-alpha.1](https://github.com/scribd/datadog_backup/compare/v0.10.2...v0.11.0-alpha.1) (2020-11-24)
1
+ ## [1.0.1-alpha.1](https://github.com/scribd/datadog_backup/compare/v1.0.0...v1.0.1-alpha.1) (2021-03-10)
2
+
3
+ # [1.0.0](https://github.com/scribd/datadog_backup/compare/v0.11.0...v1.0.0) (2021-03-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * handle gets with no result ([8d016a1](https://github.com/scribd/datadog_backup/commit/8d016a1858b44d374a0dff121c71340bf18062e0))
2
9
 
3
10
 
4
11
  ### Features
5
12
 
6
- * trigger release ([8865cad](https://github.com/scribd/datadog_backup/commit/8865cad798e2b8665a451ba76f62220b4dd2030f))
13
+ * If resource doesn't exist in Datadog, the resource is recreated. ([18ba241](https://github.com/scribd/datadog_backup/commit/18ba24183e136f9d899351bbb0999aba2c22308f))
14
+
15
+
16
+ ### BREAKING CHANGES
17
+
18
+ * `datadog-backup` used to exit with an error if a resource
19
+ wasn't found in Datadog.
20
+
21
+ # [0.11.0](https://github.com/scribd/datadog_backup/compare/v0.10.3...v0.11.0) (2021-01-12)
22
+
23
+
24
+ ### Features
25
+
26
+ * 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))
27
+
28
+ ## [0.10.3](https://github.com/scribd/datadog_backup/compare/v0.10.2...v0.10.3) (2020-12-11)
29
+
30
+
31
+ ### Performance Improvements
32
+
33
+ * coerce patch release ([bc86649](https://github.com/scribd/datadog_backup/commit/bc86649b874cd5be1da2f6bc0d1b1ecd0728676c))
7
34
 
8
35
  ## [0.10.2](https://github.com/scribd/datadog_backup/compare/v0.10.1...v0.10.2) (2020-11-03)
9
36
 
data/Gemfile CHANGED
@@ -9,4 +9,5 @@ group :development, :test do
9
9
  gem 'guard-rspec'
10
10
  gem 'rspec'
11
11
  gem 'rubocop'
12
+ gem 'rubocop-rspec'
12
13
  end
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('--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(
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
 
@@ -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.2'
23
- spec.add_dependency 'concurrent-ruby', '1.1.7'
22
+ spec.add_dependency 'amazing_print', '1.3.0'
23
+ spec.add_dependency 'concurrent-ruby', '1.1.8'
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.42.0'
27
+ spec.add_dependency 'dogapi', '1.45.0'
28
28
 
29
29
  spec.add_development_dependency 'bundler'
30
30
  spec.add_development_dependency 'pry'
@@ -108,27 +108,30 @@ module DatadogBackup
108
108
  id, diff = *future.value!
109
109
  next unless diff
110
110
 
111
- puts '--------------------------------------------------------------------------------'
112
- puts format_diff_output([id, diff])
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(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 'Invalid response, please try again.'
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
 
@@ -47,6 +47,9 @@ module DatadogBackup
47
47
  with_200 do
48
48
  api_service.request(Net::HTTP::Get, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, nil, false)
49
49
  end
50
+ rescue RuntimeError => e
51
+ return {} if e.message.include?('Request failed with error ["404"')
52
+ raise e.message
50
53
  end
51
54
 
52
55
  def get_all
@@ -73,12 +76,38 @@ module DatadogBackup
73
76
  self.class.to_s.split(':').last.downcase
74
77
  end
75
78
 
79
+ # Calls out to Datadog and checks for a '200' response
80
+ def create(body)
81
+ result = with_200 do
82
+ api_service.request(Net::HTTP::Post, "/api/#{api_version}/#{api_resource_name}", nil, body, true)
83
+ end
84
+ logger.warn 'Successfully created in datadog.'
85
+ result
86
+ end
87
+
76
88
  # Calls out to Datadog and checks for a '200' response
77
89
  def update(id, body)
78
- with_200 do
90
+ result = with_200 do
79
91
  api_service.request(Net::HTTP::Put, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, body, true)
80
92
  end
81
93
  logger.warn 'Successfully restored to datadog.'
94
+ result
95
+ end
96
+
97
+ def restore(id)
98
+ body = load_from_file_by_id(id)
99
+ begin
100
+ update(id, body)
101
+ rescue RuntimeError => e
102
+ if e.message.include?('Request failed with error ["404"')
103
+ new_id = create(body).fetch('id')
104
+
105
+ FileUtils.rm(find_file_by_id(id))
106
+ get_and_write_file(new_id)
107
+ else
108
+ raise e.message
109
+ end
110
+ end
82
111
  end
83
112
 
84
113
  def with_200
@@ -94,9 +123,8 @@ module DatadogBackup
94
123
  sleep(0.1 * retries**5) # 0.1, 3.2, 24.3, 102.4 seconds per retry
95
124
  retry
96
125
  else
97
- raise "Request failed with error #{e.message}"
126
+ raise "Net::OpenTimeout: #{e.message}"
98
127
  end
99
128
  end
100
-
101
129
  end
102
130
  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
@@ -27,7 +27,8 @@ module DatadogBackup
27
27
  end
28
28
 
29
29
  def get_by_id(id)
30
- except(all_monitors.select { |monitor| monitor['id'].to_s == id.to_s }.first)
30
+ monitor = all_monitors.select { |monitor| monitor['id'].to_s == id.to_s }.first
31
+ monitor.nil? ? {} : except(monitor)
31
32
  end
32
33
 
33
34
  def initialize(options)
@@ -42,5 +42,9 @@ module DatadogBackup
42
42
  def resources
43
43
  @options[:resources]
44
44
  end
45
+
46
+ def force_restore
47
+ @options[:force_restore]
48
+ end
45
49
  end
46
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
- VERSION = '0.11.0.alpha.1'
4
+ VERSION = '1.0.1.alpha.1'
5
5
  end
data/release.config.js CHANGED
@@ -1,6 +1,13 @@
1
1
  module.exports = {
2
2
  "plugins": [
3
- "@semantic-release/commit-analyzer",
3
+ [
4
+ "@semantic-release/commit-analyzer",
5
+ {
6
+ "releaseRules": [
7
+ {"type": "deps", "release": "patch"}
8
+ ]
9
+ }
10
+ ],
4
11
  "@semantic-release/release-notes-generator",
5
12
  [
6
13
  "@semantic-release/changelog",
@@ -19,10 +19,10 @@ describe DatadogBackup::Cli do
19
19
  resources: [DatadogBackup::Dashboards]
20
20
  }
21
21
  end
22
- let(:cli) { DatadogBackup::Cli.new(options) }
22
+ let(:cli) { described_class.new(options) }
23
23
  let(:dashboards) { DatadogBackup::Dashboards.new(options) }
24
24
 
25
- before(:example) do
25
+ before do
26
26
  allow(cli).to receive(:resource_instances).and_return([dashboards])
27
27
  end
28
28
 
@@ -39,15 +39,28 @@ describe DatadogBackup::Cli do
39
39
  }
40
40
  ]
41
41
  end
42
- before(:example) do
42
+
43
+ before do
43
44
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/stillthere.json")
44
45
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/alsostillthere.json")
45
46
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/deleted.json")
46
47
 
47
48
  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', {}])
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', {}])
51
64
  end
52
65
 
53
66
  it 'deletes the file locally as well' do
@@ -58,16 +71,18 @@ describe DatadogBackup::Cli do
58
71
  end
59
72
 
60
73
  describe '#diffs' do
61
- before(:example) do
74
+ subject { cli.diffs }
75
+
76
+ before do
62
77
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs1.json")
63
78
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs2.json")
64
79
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs3.json")
65
80
  allow(dashboards).to receive(:get_by_id).and_return({ 'text' => 'diff2' })
66
81
  allow(cli).to receive(:initialize_client).and_return(client_double)
67
82
  end
68
- subject { cli.diffs }
83
+
69
84
  it {
70
- is_expected.to include(
85
+ expect(subject).to include(
71
86
  " ---\n id: diffs1\n ---\n-text: diff2\n+text: diff\n",
72
87
  " ---\n id: diffs3\n ---\n-text: diff2\n+text: diff\n",
73
88
  " ---\n id: diffs2\n ---\n-text: diff2\n+text: diff\n"
@@ -76,14 +91,14 @@ describe DatadogBackup::Cli do
76
91
  end
77
92
 
78
93
  describe '#restore' do
79
- before(:example) do
94
+ subject { cli.restore }
95
+
96
+ before do
80
97
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs1.json")
81
98
  allow(dashboards).to receive(:get_by_id).and_return({ 'text' => 'diff2' })
82
99
  allow(cli).to receive(:initialize_client).and_return(client_double)
83
100
  end
84
101
 
85
- subject { cli.restore }
86
-
87
102
  example 'starts interactive restore' do
88
103
  allow($stdin).to receive(:gets).and_return('q')
89
104
 
@@ -98,21 +113,24 @@ describe DatadogBackup::Cli do
98
113
  expect(dashboards).to receive(:update).with('diffs1', { 'text' => 'diff' })
99
114
  subject
100
115
  end
116
+
101
117
  example 'download' do
102
118
  allow($stdin).to receive(:gets).and_return('d')
103
119
  expect(dashboards).to receive(:write_file).with(%({\n "text": "diff2"\n}), "#{tempdir}/dashboards/diffs1.json")
104
120
  subject
105
121
  end
122
+
106
123
  example 'skip' do
107
124
  allow($stdin).to receive(:gets).and_return('s')
108
- expect(dashboards).to_not receive(:write_file)
109
- expect(dashboards).to_not receive(:update)
125
+ expect(dashboards).not_to receive(:write_file)
126
+ expect(dashboards).not_to receive(:update)
110
127
  subject
111
128
  end
129
+
112
130
  example 'quit' do
113
131
  allow($stdin).to receive(:gets).and_return('q')
114
- expect(dashboards).to_not receive(:write_file)
115
- expect(dashboards).to_not receive(:update)
132
+ expect(dashboards).not_to receive(:write_file)
133
+ expect(dashboards).not_to receive(:update)
116
134
  expect { subject }.to raise_error(SystemExit)
117
135
  end
118
136
  end
@@ -7,7 +7,7 @@ describe DatadogBackup::Core do
7
7
  let(:client_double) { double }
8
8
  let(:tempdir) { Dir.mktmpdir }
9
9
  let(:core) do
10
- DatadogBackup::Core.new(
10
+ described_class.new(
11
11
  action: 'backup',
12
12
  api_service: api_service_double,
13
13
  client: client_double,
@@ -21,18 +21,19 @@ describe DatadogBackup::Core do
21
21
 
22
22
  describe '#client' do
23
23
  subject { core.client }
24
+
24
25
  it { is_expected.to eq client_double }
25
26
  end
26
27
 
27
28
  describe '#with_200' do
28
29
  context 'with 200' do
29
- subject { core.with_200 {['200', { foo: :bar }]} }
30
+ subject { core.with_200 { ['200', { foo: :bar }] } }
30
31
 
31
32
  it { is_expected.to eq({ foo: :bar }) }
32
33
  end
33
34
 
34
35
  context 'with not 200' do
35
- subject { core.with_200 {['400', "Error message"]} }
36
+ subject { core.with_200 { ['400', 'Error message'] } }
36
37
 
37
38
  it 'raises an error' do
38
39
  expect { subject }.to raise_error(RuntimeError)
@@ -41,14 +42,15 @@ describe DatadogBackup::Core do
41
42
  end
42
43
 
43
44
  describe '#diff' do
44
- before(:example) do
45
+ subject { core.diff('diff') }
46
+
47
+ before do
45
48
  allow(core).to receive(:get_by_id).and_return({ 'text' => 'diff1', 'extra' => 'diff1' })
46
49
  core.write_file('{"text": "diff2", "extra": "diff2"}', "#{tempdir}/core/diff.json")
47
50
  end
48
51
 
49
- subject { core.diff('diff') }
50
52
  it {
51
- is_expected.to eq <<~EOF
53
+ expect(subject).to eq <<~EOF
52
54
  ---
53
55
  -extra: diff1
54
56
  -text: diff1
@@ -60,11 +62,13 @@ describe DatadogBackup::Core do
60
62
 
61
63
  describe '#except' do
62
64
  subject { core.except({ a: :b, b: :c }) }
65
+
63
66
  it { is_expected.to eq({ a: :b, b: :c }) }
64
67
  end
65
68
 
66
69
  describe '#initialize' do
67
70
  subject { core }
71
+
68
72
  it 'makes the subdirectories' do
69
73
  expect(FileUtils).to receive(:mkdir_p).with("#{tempdir}/core")
70
74
  subject
@@ -73,18 +77,93 @@ describe DatadogBackup::Core do
73
77
 
74
78
  describe '#myclass' do
75
79
  subject { core.myclass }
80
+
76
81
  it { is_expected.to eq 'core' }
77
82
  end
78
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
+
79
101
  describe '#update' do
80
- subject { core.update('abc-123-def', '{"a": "b"}') }
102
+ subject { core.update('abc-123-def', { 'a' => 'b' }) }
103
+
81
104
  example 'it calls Dogapi::APIService.request' do
82
105
  stub_const('Dogapi::APIService::API_VERSION', 'v1')
83
106
  allow(core).to receive(:api_service).and_return(api_service_double)
84
107
  allow(core).to receive(:api_version).and_return('v1')
85
108
  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])
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' }])
87
114
  subject
88
115
  end
89
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
90
169
  end
@@ -7,7 +7,7 @@ describe DatadogBackup::Dashboards do
7
7
  let(:client_double) { double }
8
8
  let(:tempdir) { Dir.mktmpdir }
9
9
  let(:dashboards) do
10
- DatadogBackup::Dashboards.new(
10
+ described_class.new(
11
11
  action: 'backup',
12
12
  client: client_double,
13
13
  backup_dir: tempdir,
@@ -59,10 +59,13 @@ describe DatadogBackup::Dashboards do
59
59
  'title' => 'example dashboard'
60
60
  }
61
61
  end
62
- before(:example) do
62
+
63
+ before do
63
64
  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)
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)
66
69
  end
67
70
 
68
71
  describe '#backup' do
@@ -100,17 +103,19 @@ describe DatadogBackup::Dashboards do
100
103
  -title: example dashboard
101
104
  +a: b
102
105
  EOF
103
- )
106
+ )
104
107
  end
105
108
  end
106
109
 
107
110
  describe '#except' do
108
111
  subject { dashboards.except({ :a => :b, 'modified_at' => :c, 'url' => :d }) }
112
+
109
113
  it { is_expected.to eq({ a: :b }) }
110
114
  end
111
115
 
112
116
  describe '#get_by_id' do
113
117
  subject { dashboards.get_by_id('abc-123-def') }
118
+
114
119
  it { is_expected.to eq board_abc_123_def }
115
120
  end
116
121
  end
@@ -27,55 +27,61 @@ describe DatadogBackup::LocalFilesystem do
27
27
  end
28
28
 
29
29
  describe '#all_files' do
30
- before(:example) do
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(:example) do
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
- before(:example) do
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(:example) do
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
- before(:example) do
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(:example) do
68
+ after do
65
69
  FileUtils.rm "#{tempdir}/core/abc-123-def.json"
66
70
  end
67
- subject { core.class_from_id('abc-123-def') }
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
- before(:example) do
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(:example) do
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
- before(:example) do
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(:example) do
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
@@ -7,7 +7,7 @@ describe DatadogBackup::Monitors do
7
7
  let(:client_double) { double }
8
8
  let(:tempdir) { Dir.mktmpdir }
9
9
  let(:monitors) do
10
- DatadogBackup::Monitors.new(
10
+ described_class.new(
11
11
  action: 'backup',
12
12
  client: client_double,
13
13
  backup_dir: tempdir,
@@ -49,14 +49,17 @@ describe DatadogBackup::Monitors do
49
49
  ]
50
50
  end
51
51
 
52
- before(:example) do
52
+ before 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
59
61
  subject { monitors.all_monitors }
62
+
60
63
  it { is_expected.to eq [monitor_description] }
61
64
  end
62
65
 
@@ -100,16 +103,20 @@ describe DatadogBackup::Monitors do
100
103
 
101
104
  describe '#filename' do
102
105
  subject { monitors.filename(123_455) }
106
+
103
107
  it { is_expected.to eq("#{tempdir}/monitors/123455.json") }
104
108
  end
105
109
 
106
110
  describe '#get_by_id' do
107
111
  context 'Integer' do
108
112
  subject { monitors.get_by_id(123_455) }
113
+
109
114
  it { is_expected.to eq monitor_description }
110
115
  end
116
+
111
117
  context 'String' do
112
118
  subject { monitors.get_by_id('123455') }
119
+
113
120
  it { is_expected.to eq monitor_description }
114
121
  end
115
122
  end
@@ -47,7 +47,7 @@ describe 'bin/datadog_backup' do
47
47
  it "dies unless given ENV[#{v}]" do
48
48
  ClimateControl.env[v] = nil
49
49
  _, status = run_bin('backup')
50
- expect(status).to_not be_success
50
+ expect(status).not_to be_success
51
51
  end
52
52
  end
53
53
 
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.alpha.1
4
+ version: 1.0.1.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: 2020-11-24 00:00:00.000000000 Z
12
+ date: 2021-03-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: amazing_print
@@ -17,28 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 1.2.2
20
+ version: 1.3.0
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.2
27
+ version: 1.3.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: concurrent-ruby
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - '='
33
33
  - !ruby/object:Gem::Version
34
- version: 1.1.7
34
+ version: 1.1.8
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - '='
40
40
  - !ruby/object:Gem::Version
41
- version: 1.1.7
41
+ version: 1.1.8
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: concurrent-ruby-edge
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -87,14 +87,14 @@ dependencies:
87
87
  requirements:
88
88
  - - '='
89
89
  - !ruby/object:Gem::Version
90
- version: 1.42.0
90
+ version: 1.45.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.42.0
97
+ version: 1.45.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