datadog_backup 3.0.0 → 3.1.0

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