datadog_backup 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0eec1a1c9c37c415e69f59bccdc5fb28cfc2260b4cf40941c283a588c89727e8
4
- data.tar.gz: 202db8cd658b13977d8c9e1dc3248e8bf33411aeeb4102e669f9a572c92dce39
3
+ metadata.gz: f24893d65b7350e2c22c2f1f89068664f9d4dd932231d292a26ae4b5f0c87a57
4
+ data.tar.gz: d7a3a5e175b128a3e11bf523d5fa8fbd9b3c890260a3e14bb74ba8688f0aef06
5
5
  SHA512:
6
- metadata.gz: 48d83c230a6ee5a17957e5c5da124911529e28a230170c3556105639025497d79e8528555cbf8e37b00abc70256399addbaabc1d8101dd367574d248557826af
7
- data.tar.gz: 9bcb707a074415be48f1f687f29e524ebcbfbbe60ca85dd7c56a95e3a6d0bcec7606da3504045b716b012c03c3c2a4a16d3808f1150e3e2dfd3a0101d29b7d41
6
+ metadata.gz: bd41dd652e26e9d049d25439c81b29a7be45da046526188bc77e0ffd2e06607e25044d10d78d72a0c35066c4b83919f2bcfb435136f9582240f11fcf035c13d6
7
+ data.tar.gz: 256dd9b0eb76878f7966a853a644c39aede938882781f13e5b7577db4e09f97600c57748858a75aebcff0cd0a3ca32e2a4358618bb0481eea5568469bb57abe8
@@ -44,10 +44,14 @@ jobs:
44
44
  uses: cycjimmy/semantic-release-action@v3
45
45
  env:
46
46
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47
- GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_TOKEN }}
48
47
  with:
49
48
  semantic_version: 17
50
49
  extra_plugins: |
51
50
  @semantic-release/changelog@5
52
51
  @semantic-release/git@9
53
- semantic-release-rubygem@1
52
+ - name: push to rubygems
53
+ if: ${{ steps.semantic.output.new_release_published }}
54
+ env:
55
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_TOKEN }}
56
+ run: |
57
+ gem push datadog_backup.gem
data/.rubocop.yml CHANGED
@@ -1,78 +1,37 @@
1
- require: rubocop-rspec
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://docs.rubocop.org/rubocop/configuration
11
+ require:
12
+ - rubocop-rspec
2
13
 
3
- Gemspec/DateAssignment: # (new in 1.10)
4
- Enabled: true
5
- Layout/LineEndStringConcatenationIndentation: # (new in 1.18)
6
- Enabled: true
7
- Layout/SpaceBeforeBrackets: # (new in 1.7)
8
- Enabled: true
9
- Lint/AmbiguousAssignment: # (new in 1.7)
10
- Enabled: true
11
- Lint/DeprecatedConstants: # (new in 1.8)
12
- Enabled: true
13
- Lint/DuplicateBranch: # (new in 1.3)
14
- Enabled: true
15
- Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
16
- Enabled: true
17
- Lint/EmptyBlock: # (new in 1.1)
18
- Enabled: true
19
- Lint/EmptyClass: # (new in 1.3)
20
- Enabled: true
21
- Lint/EmptyInPattern: # (new in 1.16)
22
- Enabled: true
23
- Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
24
- Enabled: true
25
- Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
26
- Enabled: true
27
- Lint/NumberedParameterAssignment: # (new in 1.9)
28
- Enabled: true
29
- Lint/OrAssignmentToConstant: # (new in 1.9)
30
- Enabled: true
31
- Lint/RedundantDirGlobSort: # (new in 1.8)
32
- Enabled: true
33
- Lint/SymbolConversion: # (new in 1.9)
34
- Enabled: true
35
- Lint/ToEnumArguments: # (new in 1.1)
36
- Enabled: true
37
- Lint/TripleQuotes: # (new in 1.9)
38
- Enabled: true
39
- Lint/UnexpectedBlockArity: # (new in 1.5)
40
- Enabled: true
41
- Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
42
- Enabled: true
43
- Naming/InclusiveLanguage: # (new in 1.18)
44
- Enabled: true
45
- Style/ArgumentsForwarding: # (new in 1.1)
46
- Enabled: true
47
- Style/CollectionCompact: # (new in 1.2)
48
- Enabled: true
49
- Style/DocumentDynamicEvalDefinition: # (new in 1.1)
50
- Enabled: true
51
- Style/EndlessMethod: # (new in 1.8)
52
- Enabled: true
53
- Style/HashConversion: # (new in 1.10)
54
- Enabled: true
55
- Style/HashExcept: # (new in 1.7)
56
- Enabled: true
57
- Style/IfWithBooleanLiteralBranches: # (new in 1.9)
58
- Enabled: true
59
- Style/InPatternThen: # (new in 1.16)
60
- Enabled: true
61
- Style/MultilineInPatternThen: # (new in 1.16)
62
- Enabled: true
63
- Style/NegatedIfElseCondition: # (new in 1.2)
64
- Enabled: true
65
- Style/NilLambda: # (new in 1.3)
66
- Enabled: true
67
- Style/QuotedSymbols: # (new in 1.16)
68
- Enabled: true
69
- Style/RedundantArgument: # (new in 1.4)
70
- Enabled: true
71
- Style/StringChars: # (new in 1.12)
72
- Enabled: true
73
- Style/SwapValues: # (new in 1.1)
74
- Enabled: true
75
- RSpec/IdenticalEqualityAssertion: # (new in 2.4)
76
- Enabled: true
77
- RSpec/Rails/AvoidSetupHook: # (new in 2.4)
78
- Enabled: true
14
+ AllCops:
15
+ TargetRubyVersion: 2.7
16
+ NewCops: enable
17
+
18
+ Layout/LineLength:
19
+ Enabled: false
20
+
21
+ Metrics/BlockLength:
22
+ Enabled: false
23
+
24
+ Metrics/ClassLength:
25
+ Enabled: false
26
+
27
+ Metrics/MethodLength:
28
+ Enabled: false
29
+
30
+ Naming/AccessorMethodName:
31
+ Enabled: false
32
+
33
+ RSpec/MultipleMemoizedHelpers:
34
+ Enabled: false
35
+
36
+ RSpec/ExampleLength:
37
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [3.1.0](https://github.com/scribd/datadog_backup/compare/v3.0.0...v3.1.0) (2022-08-30)
2
+
3
+
4
+ ### Features
5
+
6
+ * backup and restore synthetics ([#139](https://github.com/scribd/datadog_backup/issues/139)) ([a46cadc](https://github.com/scribd/datadog_backup/commit/a46cadc7d196dcb0f20bf31d06cde6a13a390835))
7
+
1
8
  # [3.0.0](https://github.com/scribd/datadog_backup/compare/v2.0.2...v3.0.0) (2022-08-25)
2
9
 
3
10
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- datadog_backup (3.0.0.alpha.2)
4
+ datadog_backup (3.0.0)
5
5
  amazing_print
6
6
  concurrent-ruby
7
7
  deepsort
@@ -62,7 +62,7 @@ GEM
62
62
  byebug (~> 11.0)
63
63
  pry (>= 0.13, < 0.15)
64
64
  rainbow (3.1.1)
65
- rb-fsevent (0.11.1)
65
+ rb-fsevent (0.11.2)
66
66
  rb-inotify (0.10.1)
67
67
  ffi (~> 1.0)
68
68
  regexp_parser (2.5.0)
data/README.md CHANGED
@@ -16,7 +16,7 @@ Additional features may be built out over time.
16
16
  ## Breaking Changes
17
17
  v3 is a backwards incompatible change.
18
18
 
19
- - [] DATADOG_API_KEY and DATADOG_APP_KEY are no longer the environment variables used to authenticate to Datadog. Instead, set the environment variables DD_API_KEY and DD_APP_KEY.
19
+ - [ ] DATADOG_API_KEY and DATADOG_APP_KEY are no longer the environment variables used to authenticate to Datadog. Instead, set the environment variables DD_API_KEY and DD_APP_KEY.
20
20
  - [ ] ruby 2.6 is no longer supported. Please upgrade to ruby 2.7 or higher.
21
21
  - [ ] The options `--ssh` and `--ssshh` are no longer supported. Instead, please use `--quiet` to supress logging. `--debug` remains supported.
22
22
  - [ ] The environment variable `DATADOG_HOST` is no longer supported. Instead, please use `DD_SITE_URL`.
data/bin/datadog_backup CHANGED
@@ -11,7 +11,6 @@ LOGGER.level = Logger::INFO
11
11
 
12
12
  require 'datadog_backup'
13
13
 
14
-
15
14
  def fatal(message)
16
15
  LOGGER.fatal(message)
17
16
  exit 1
@@ -19,10 +18,10 @@ end
19
18
 
20
19
  def options_valid?(options)
21
20
  %w[backup diffs restore].include?(options[:action])
22
- %w[DD_API_KEY DD_APP_KEY].all? { |key| ENV[key] }
21
+ %w[DD_API_KEY DD_APP_KEY].all? { |key| ENV.fetch(key, nil) }
23
22
  end
24
23
 
25
- def prereqs(defaults)
24
+ def prereqs(defaults) # rubocop:disable Metrics/AbcSize
26
25
  ARGV << '--help' if ARGV.empty?
27
26
 
28
27
  result = defaults.dup
@@ -49,6 +48,9 @@ def prereqs(defaults)
49
48
  opts.on('--dashboards-only') do
50
49
  result[:resources] = [DatadogBackup::Dashboards]
51
50
  end
51
+ opts.on('--synthetics-only') do
52
+ result[:resources] = [DatadogBackup::Synthetics]
53
+ end
52
54
  opts.on(
53
55
  '--json',
54
56
  'format backups as JSON instead of YAML. Does not impact `diffs` nor `restore`, but do not mix formats in the same backup-dir.'
@@ -78,9 +80,9 @@ defaults = {
78
80
  action: nil,
79
81
  backup_dir: File.join(ENV.fetch('PWD'), 'backup'),
80
82
  diff_format: :color,
81
- resources: [DatadogBackup::Dashboards, DatadogBackup::Monitors],
83
+ resources: [DatadogBackup::Dashboards, DatadogBackup::Monitors, DatadogBackup::Synthetics],
82
84
  output_format: :yaml,
83
85
  force_restore: false
84
86
  }
85
87
 
86
- DatadogBackup::Cli.new(prereqs(defaults)).run!
88
+ DatadogBackup::Cli.new(prereqs(defaults)).run!
@@ -13,13 +13,13 @@ Gem::Specification.new do |spec|
13
13
  spec.description = 'A utility to backup and restore Datadog accounts'
14
14
  spec.homepage = 'https://github.com/scribd/datadog_backup'
15
15
  spec.license = 'MIT'
16
+ spec.metadata['rubygems_mfa_required'] = 'true'
16
17
 
17
18
  spec.files = `git ls-files -z`.split("\x0")
18
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^spec/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.required_ruby_version = ['>= 2.7']
22
+ spec.required_ruby_version = '>= 2.7'
23
23
 
24
24
  spec.add_dependency 'amazing_print'
25
25
  spec.add_dependency 'concurrent-ruby'
@@ -28,11 +28,10 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency 'faraday'
29
29
  spec.add_dependency 'faraday-retry'
30
30
 
31
-
32
31
  spec.add_development_dependency 'bundler'
32
+ spec.add_development_dependency 'guard-rspec'
33
33
  spec.add_development_dependency 'pry'
34
34
  spec.add_development_dependency 'pry-byebug'
35
- spec.add_development_dependency 'guard-rspec'
36
35
  spec.add_development_dependency 'rspec'
37
36
  spec.add_development_dependency 'rubocop'
38
37
  spec.add_development_dependency 'rubocop-rspec'
@@ -4,6 +4,7 @@ require 'optparse'
4
4
  require 'amazing_print'
5
5
 
6
6
  module DatadogBackup
7
+ # CLI is the command line interface for the datadog_backup gem.
7
8
  class Cli
8
9
  include ::DatadogBackup::Options
9
10
 
@@ -11,9 +12,9 @@ module DatadogBackup
11
12
  LOGGER.info("Starting diffs on #{::DatadogBackup::ThreadPool::TPOOL.max_length} threads")
12
13
  any_resource_instance
13
14
  .all_file_ids_for_selected_resources
14
- .map do |id|
15
- Concurrent::Promises.future_on(::DatadogBackup::ThreadPool::TPOOL, id) do |id|
16
- [id, getdiff(id)]
15
+ .map do |file_id|
16
+ Concurrent::Promises.future_on(::DatadogBackup::ThreadPool::TPOOL, file_id) do |fid|
17
+ [fid, getdiff(fid)]
17
18
  end
18
19
  end
19
20
  end
@@ -32,32 +33,17 @@ module DatadogBackup
32
33
  matching_resource_instance(any_resource_instance.class_from_id(id))
33
34
  end
34
35
 
35
- def diffs
36
- futures = all_diff_futures
37
- ::DatadogBackup::ThreadPool.watcher.join
38
-
39
- format_diff_output(
40
- Concurrent::Promises
41
- .zip(*futures)
42
- .value!
43
- .compact
44
- )
45
- end
46
-
47
36
  def getdiff(id)
48
37
  result = definitive_resource_instance(id).diff(id)
49
38
  case result
50
- when ''
51
- nil
52
- when "\n"
53
- nil
54
- when '<div class="diff"></div>'
39
+ when '---' || '' || "\n" || '<div class="diff"></div>'
55
40
  nil
56
41
  else
57
42
  result
58
43
  end
59
44
  end
60
45
 
46
+ # rubocop:disable Style/StringConcatenation
61
47
  def format_diff_output(diff_output)
62
48
  case diff_format
63
49
  when nil, :color
@@ -69,58 +55,31 @@ module DatadogBackup
69
55
  Diffy::CSS +
70
56
  '</style></head><body>' +
71
57
  diff_output.map do |id, diff|
72
- "<br><br> ---<br><strong> id: #{id}</strong><br>" + diff
58
+ "<br><br> ---<br><strong> id: #{id}</strong><br>#{diff}"
73
59
  end.join('<br>') +
74
60
  '</body></html>'
75
61
  else
76
62
  raise 'Unexpected diff_format.'
77
63
  end
78
64
  end
65
+ # rubocop:enable Style/StringConcatenation
79
66
 
80
67
  def initialize(options)
81
68
  @options = options
82
69
  end
83
70
 
84
- def matching_resource_instance(klass)
85
- resource_instances.select { |resource_instance| resource_instance.instance_of?(klass) }.first
86
- end
87
-
88
- def resource_instances
89
- @resource_instances ||= resources.map do |resource|
90
- resource.new(@options)
91
- end
92
- end
93
-
94
71
  def restore
95
72
  futures = all_diff_futures
96
73
  watcher = ::DatadogBackup::ThreadPool.watcher
97
74
 
98
75
  futures.each do |future|
99
76
  id, diff = *future.value!
100
- next unless diff
77
+ next if diff.nil? || diff.empty?
101
78
 
102
79
  if @options[:force_restore]
103
80
  definitive_resource_instance(id).restore(id)
104
81
  else
105
- puts '--------------------------------------------------------------------------------'
106
- puts format_diff_output([id, diff])
107
- puts '(r)estore to Datadog, overwrite local changes and (d)ownload, (s)kip, or (q)uit?'
108
- response = $stdin.gets.chomp
109
- case response
110
- when 'q'
111
- exit
112
- when 'r'
113
- puts "Restoring #{id} to Datadog."
114
- definitive_resource_instance(id).restore(id)
115
- when 'd'
116
- puts "Downloading #{id} from Datadog."
117
- definitive_resource_instance(id).get_and_write_file(id)
118
- when 's'
119
- next
120
- else
121
- puts 'Invalid response, please try again.'
122
- response = $stdin.gets.chomp
123
- end
82
+ ask_to_restore(id, diff)
124
83
  end
125
84
  end
126
85
  watcher.join if watcher.status
@@ -131,5 +90,42 @@ module DatadogBackup
131
90
  rescue SystemExit, Interrupt
132
91
  ::DatadogBackup::ThreadPool.shutdown
133
92
  end
93
+
94
+ private
95
+
96
+ def ask_to_restore(id, diff)
97
+ puts '--------------------------------------------------------------------------------'
98
+ puts format_diff_output([id, diff])
99
+ puts '(r)estore to Datadog, overwrite local changes and (d)ownload, (s)kip, or (q)uit?'
100
+ loop do
101
+ response = $stdin.gets.chomp
102
+ case response
103
+ when 'q'
104
+ exit
105
+ when 'r'
106
+ puts "Restoring #{id} to Datadog."
107
+ definitive_resource_instance(id).restore(id)
108
+ break
109
+ when 'd'
110
+ puts "Downloading #{id} from Datadog."
111
+ definitive_resource_instance(id).get_and_write_file(id)
112
+ break
113
+ when 's'
114
+ break
115
+ else
116
+ puts 'Invalid response, please try again.'
117
+ end
118
+ end
119
+ end
120
+
121
+ def matching_resource_instance(klass)
122
+ resource_instances.select { |resource_instance| resource_instance.instance_of?(klass) }.first
123
+ end
124
+
125
+ def resource_instances
126
+ @resource_instances ||= resources.map do |resource|
127
+ resource.new(@options)
128
+ end
129
+ end
134
130
  end
135
131
  end
@@ -5,14 +5,14 @@ require 'deepsort'
5
5
  require 'faraday'
6
6
  require 'faraday/retry'
7
7
 
8
-
9
-
10
8
  module DatadogBackup
9
+ # The default options for backing up and restores.
10
+ # This base class is meant to be extended by specific resources, such as Dashboards, Monitors, and so on.
11
11
  class Core
12
12
  include ::DatadogBackup::LocalFilesystem
13
13
  include ::DatadogBackup::Options
14
14
 
15
- @@retry_options = {
15
+ @retry_options = {
16
16
  max: 5,
17
17
  interval: 0.05,
18
18
  interval_randomness: 0.5,
@@ -20,27 +20,27 @@ module DatadogBackup
20
20
  }
21
21
 
22
22
  def api_service
23
- conn ||= Faraday.new(
24
- url: api_url,
25
- headers: {
26
- 'DD-API-KEY' => ENV.fetch('DD_API_KEY'),
27
- 'DD-APPLICATION-KEY' => ENV.fetch('DD_APP_KEY')
28
- }
29
- ) do |faraday|
30
- faraday.request :json
31
- faraday.request :retry, @@retry_options
32
- faraday.response(:logger, LOGGER, {headers: true, bodies: LOGGER.debug?, log_level: :debug}) do | logger |
33
- logger.filter(/(DD-API-KEY:)([^&]+)/, '\1[REDACTED]')
34
- logger.filter(/(DD-APPLICATION-KEY:)([^&]+)/, '\1[REDACTED]')
35
- end
36
- faraday.response :raise_error
37
- faraday.response :json
38
- faraday.adapter Faraday.default_adapter
39
- end
23
+ @api_service ||= Faraday.new(
24
+ url: api_url,
25
+ headers: {
26
+ 'DD-API-KEY' => ENV.fetch('DD_API_KEY'),
27
+ 'DD-APPLICATION-KEY' => ENV.fetch('DD_APP_KEY')
28
+ }
29
+ ) do |faraday|
30
+ faraday.request :json
31
+ faraday.request :retry, @retry_options
32
+ faraday.response(:logger, LOGGER, { headers: true, bodies: LOGGER.debug?, log_level: :debug }) do |logger|
33
+ logger.filter(/(DD-API-KEY:)([^&]+)/, '\1[REDACTED]')
34
+ logger.filter(/(DD-APPLICATION-KEY:)([^&]+)/, '\1[REDACTED]')
35
+ end
36
+ faraday.response :raise_error
37
+ faraday.response :json
38
+ faraday.adapter Faraday.default_adapter
39
+ end
40
40
  end
41
41
 
42
42
  def api_url
43
- ENV.fetch('DD_SITE_URL', "https://api.datadoghq.com/")
43
+ ENV.fetch('DD_SITE_URL', 'https://api.datadoghq.com/')
44
44
  end
45
45
 
46
46
  def api_version
@@ -51,6 +51,11 @@ module DatadogBackup
51
51
  raise 'subclass is expected to implement #api_resource_name'
52
52
  end
53
53
 
54
+ # Some resources have a different key for the id.
55
+ def id_keyname
56
+ 'id'
57
+ end
58
+
54
59
  def backup
55
60
  raise 'subclass is expected to implement #backup'
56
61
  end
@@ -61,8 +66,8 @@ module DatadogBackup
61
66
  current = except(get_by_id(id)).deep_sort.to_yaml
62
67
  filesystem = except(load_from_file_by_id(id)).deep_sort.to_yaml
63
68
  result = ::Diffy::Diff.new(current, filesystem, include_plus_and_minus_in_html: true).to_s(diff_format)
64
- LOGGER.debug("Compared ID #{id} and found #{result}")
65
- result
69
+ LOGGER.debug("Compared ID #{id} and found filesystem: #{filesystem} <=> current: #{current} == result: #{result}")
70
+ result.chomp
66
71
  end
67
72
 
68
73
  # Returns a hash with banlist elements removed
@@ -74,6 +79,7 @@ module DatadogBackup
74
79
  end
75
80
  end
76
81
 
82
+ # Fetch the specified resource from Datadog
77
83
  def get(id)
78
84
  params = {}
79
85
  headers = {}
@@ -81,17 +87,25 @@ module DatadogBackup
81
87
  body_with_2xx(response)
82
88
  end
83
89
 
90
+ # Returns a list of all resources in Datadog
91
+ # Do not use directly, but use the child classes' #all method instead
84
92
  def get_all
93
+ return @get_all if @get_all
94
+
85
95
  params = {}
86
96
  headers = {}
87
97
  response = api_service.get("/api/#{api_version}/#{api_resource_name}", params, headers)
88
- body_with_2xx(response)
98
+ @get_all = body_with_2xx(response)
89
99
  end
90
100
 
101
+ # Download the resource from Datadog and write it to a file
91
102
  def get_and_write_file(id)
92
- write_file(dump(get_by_id(id)), filename(id))
103
+ body = get_by_id(id)
104
+ write_file(dump(body), filename(id))
105
+ body
93
106
  end
94
107
 
108
+ # Fetch the specified resource from Datadog and remove the banlist elements
95
109
  def get_by_id(id)
96
110
  except(get(id))
97
111
  end
@@ -106,43 +120,57 @@ module DatadogBackup
106
120
  self.class.to_s.split(':').last.downcase
107
121
  end
108
122
 
109
- # Calls out to Datadog and checks for a '200' response
123
+ # Create a new resource in Datadog
110
124
  def create(body)
111
125
  headers = {}
112
- response = api_service.post("/api/#{api_version}/#{api_resource_name}", body, headers)
126
+ response = api_service.post("/api/#{api_version}/#{api_resource_name}", body, headers)
113
127
  body = body_with_2xx(response)
114
- LOGGER.warn "Successfully created #{body.fetch('id')} in datadog."
128
+ LOGGER.warn "Successfully created #{body.fetch(id_keyname)} in datadog."
129
+ LOGGER.info 'Invalidating cache'
130
+ @get_all = nil
115
131
  body
116
132
  end
117
133
 
118
- # Calls out to Datadog and checks for a '200' response
134
+ # Update an existing resource in Datadog
119
135
  def update(id, body)
120
136
  headers = {}
121
137
  response = api_service.put("/api/#{api_version}/#{api_resource_name}/#{id}", body, headers)
122
138
  body = body_with_2xx(response)
123
- LOGGER.warn 'Successfully restored #{id} to datadog.'
139
+ LOGGER.warn "Successfully restored #{id} to datadog."
140
+ LOGGER.info 'Invalidating cache'
141
+ @get_all = nil
124
142
  body
125
143
  end
126
144
 
145
+ # If the resource exists in Datadog, update it. Otherwise, create it.
127
146
  def restore(id)
128
147
  body = load_from_file_by_id(id)
129
148
  begin
130
149
  update(id, body)
131
150
  rescue RuntimeError => e
132
- if e.message.include?('update failed with error 404')
133
- new_id = create(body).fetch('id')
151
+ raise e.message unless e.message.include?('update failed with error 404')
134
152
 
135
- FileUtils.rm(find_file_by_id(id))
136
- get_and_write_file(new_id)
137
- else
138
- raise e.message
139
- end
153
+ create_newly(id, body)
140
154
  end
141
155
  end
142
156
 
157
+ # Return the Faraday body from a response with a 2xx status code, otherwise raise an error
143
158
  def body_with_2xx(response)
144
- raise "#{caller_locations(1,1)[0].label} failed with error #{response.status}" unless response.status.to_s =~ /^2/
159
+ unless response.status.to_s =~ /^2/
160
+ raise "#{caller_locations(1,
161
+ 1)[0].label} failed with error #{response.status}"
162
+ end
163
+
145
164
  response.body
146
165
  end
166
+
167
+ private
168
+
169
+ # Create a new resource in Datadog, then move the old file to the new resource's ID
170
+ def create_newly(file_id, body)
171
+ new_id = create(body).fetch(id_keyname)
172
+ FileUtils.rm(find_file_by_id(file_id))
173
+ get_and_write_file(new_id)
174
+ end
147
175
  end
148
176
  end
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
+ # Dashboards specific overrides for backup and restore.
4
5
  class Dashboards < Core
6
+ def all
7
+ get_all.fetch('dashboards')
8
+ end
5
9
 
6
10
  def api_version
7
11
  'v1'
@@ -11,12 +15,15 @@ module DatadogBackup
11
15
  'dashboard'
12
16
  end
13
17
 
18
+ def id_keyname
19
+ 'id'
20
+ end
21
+
14
22
  def backup
15
23
  LOGGER.info("Starting diffs on #{::DatadogBackup::ThreadPool::TPOOL.max_length} threads")
16
-
17
- futures = all_dashboards.map do |board|
18
- Concurrent::Promises.future_on(::DatadogBackup::ThreadPool::TPOOL, board) do |board|
19
- id = board['id']
24
+ futures = all.map do |dashboard|
25
+ Concurrent::Promises.future_on(::DatadogBackup::ThreadPool::TPOOL, dashboard) do |board|
26
+ id = board[id_keyname]
20
27
  get_and_write_file(id)
21
28
  end
22
29
  end
@@ -27,10 +34,6 @@ module DatadogBackup
27
34
  Concurrent::Promises.zip(*futures).value!
28
35
  end
29
36
 
30
- def all_dashboards
31
- get_all.fetch('dashboards')
32
- end
33
-
34
37
  def initialize(options)
35
38
  super(options)
36
39
  @banlist = %w[modified_at url].freeze
@@ -1,11 +1,10 @@
1
-
1
+ # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
+ # Notify the user if they are using deprecated features.
4
5
  module Deprecations
5
6
  def self.check
6
- if RUBY_VERSION < '2.7'
7
- LOGGER.warn "ruby-#{RUBY_VERSION} is deprecated. Ruby 2.7 or higher will be required to use this gem after datadog_backup@v3"
8
- end
7
+ LOGGER.warn "ruby-#{RUBY_VERSION} is deprecated. Ruby 2.7 or higher will be required to use this gem after datadog_backup@v3" if RUBY_VERSION < '2.7'
9
8
  end
10
9
  end
11
- end
10
+ end