Class: DatadogBackup::Core

Inherits:
Object
  • Object
show all
Includes:
LocalFilesystem, Options
Defined in:
lib/datadog_backup/core.rb

Direct Known Subclasses

Dashboards, Monitors

Instance Method Summary collapse

Methods included from Options

#action, #backup_dir, #client, #concurrency_limit, #datadog_api_key, #datadog_app_key, #diff_format, #force_restore, #logger, #output_format, #resources

Methods included from LocalFilesystem

#all_file_ids, #all_file_ids_for_selected_resources, #all_files, #class_from_id, #dump, #file_type, #filename, #find_file_by_id, #load_from_file, #load_from_file_by_id, #mydir, #purge, #write_file

Constructor Details

#initialize(options) ⇒ Core

Returns a new instance of Core.



70
71
72
73
74
# File 'lib/datadog_backup/core.rb', line 70

def initialize(options)
  @options = options
  @banlist = []
  ::FileUtils.mkdir_p(mydir)
end

Instance Method Details

#api_resource_nameObject



19
20
21
# File 'lib/datadog_backup/core.rb', line 19

def api_resource_name
  raise 'subclass is expected to implement #api_resource_name'
end

#api_serviceObject



11
12
13
# File 'lib/datadog_backup/core.rb', line 11

def api_service
  raise 'subclass is expected to implement #api_service'
end

#api_versionObject



15
16
17
# File 'lib/datadog_backup/core.rb', line 15

def api_version
  raise 'subclass is expected to implement #api_version'
end

#backupObject



23
24
25
# File 'lib/datadog_backup/core.rb', line 23

def backup
  raise 'subclass is expected to implement #backup'
end

#create(body) ⇒ Object

Calls out to Datadog and checks for a ‘200’ response



81
82
83
84
85
86
87
# File 'lib/datadog_backup/core.rb', line 81

def create(body)
  result = with_200 do
    api_service.request(Net::HTTP::Post, "/api/#{api_version}/#{api_resource_name}", nil, body, true)
  end
  logger.warn 'Successfully created in datadog.'
  result
end

#diff(id) ⇒ Object

Returns the diffy diff. Optionally, supply an array of keys to remove from comparison



29
30
31
32
33
34
35
# File 'lib/datadog_backup/core.rb', line 29

def diff(id)
  current = except(get_by_id(id)).deep_sort.to_yaml
  filesystem = except(load_from_file_by_id(id)).deep_sort.to_yaml
  result = ::Diffy::Diff.new(current, filesystem, include_plus_and_minus_in_html: true).to_s(diff_format)
  logger.debug("Compared ID #{id} and found #{result}")
  result
end

#except(hash) ⇒ Object

Returns a hash with banlist elements removed



38
39
40
41
42
43
44
# File 'lib/datadog_backup/core.rb', line 38

def except(hash)
  hash.tap do # tap returns self
    @banlist.each do |key|
      hash.delete(key) # delete returns the value at the deleted key, hence the tap wrapper
    end
  end
end

#get(id) ⇒ Object



46
47
48
49
50
51
52
53
54
# File 'lib/datadog_backup/core.rb', line 46

def get(id)
  with_200 do
    api_service.request(Net::HTTP::Get, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, nil, false)
  end
rescue RuntimeError => e
  return {} if e.message.include?('Request failed with error ["404"')

  raise e.message
end

#get_allObject



56
57
58
59
60
# File 'lib/datadog_backup/core.rb', line 56

def get_all
  with_200 do
    api_service.request(Net::HTTP::Get, "/api/#{api_version}/#{api_resource_name}", nil, nil, false)
  end
end

#get_and_write_file(id) ⇒ Object



62
63
64
# File 'lib/datadog_backup/core.rb', line 62

def get_and_write_file(id)
  write_file(dump(get_by_id(id)), filename(id))
end

#get_by_id(id) ⇒ Object



66
67
68
# File 'lib/datadog_backup/core.rb', line 66

def get_by_id(id)
  except(get(id))
end

#myclassObject



76
77
78
# File 'lib/datadog_backup/core.rb', line 76

def myclass
  self.class.to_s.split(':').last.downcase
end

#restore(id) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/datadog_backup/core.rb', line 98

def restore(id)
  body = load_from_file_by_id(id)
  begin
    update(id, body)
  rescue RuntimeError => e
    if e.message.include?('Request failed with error ["404"')
      new_id = create(body).fetch('id')

      FileUtils.rm(find_file_by_id(id))
      get_and_write_file(new_id)
    else
      raise e.message
    end
  end
end

#update(id, body) ⇒ Object

Calls out to Datadog and checks for a ‘200’ response



90
91
92
93
94
95
96
# File 'lib/datadog_backup/core.rb', line 90

def update(id, body)
  result = with_200 do
    api_service.request(Net::HTTP::Put, "/api/#{api_version}/#{api_resource_name}/#{id}", nil, body, true)
  end
  logger.warn 'Successfully restored to datadog.'
  result
end

#with_200Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/datadog_backup/core.rb', line 114

def with_200
  max_retries = 6
  retries ||= 0

  response = yield
  raise "Request failed with error #{response}" unless response[0] == '200'

  response[1]
rescue ::Net::OpenTimeout => e
  if (retries += 1) <= max_retries
    sleep(0.1 * retries**5) # 0.1, 3.2, 24.3, 102.4 seconds per retry
    retry
  else
    raise "Net::OpenTimeout: #{e.message}"
  end
end