mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-08-03 16:04:30 +00:00
148 lines
4.9 KiB
Ruby
148 lines
4.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Backup
|
|
module Cli
|
|
module Metadata
|
|
# Backup Metadata includes information about the Backup
|
|
class BackupMetadata
|
|
# Metadata version number should always increase when:
|
|
# - field is added
|
|
# - field is removed
|
|
# - field format/type changes
|
|
METADATA_VERSION = 2
|
|
|
|
# Metadata filename used when writing or loading from a filesystem location
|
|
METADATA_FILENAME = 'backup_information.json'
|
|
|
|
# Metadata file permissions
|
|
METADATA_FILE_MODE = 0o600 # owner: rw, group: none, all: none (-rw-------)
|
|
|
|
# List all of the current top level fields along with their expected data
|
|
# type name to specify how to parse and serialize values
|
|
METADATA_SCHEMA = {
|
|
metadata_version: :integer,
|
|
backup_id: :string,
|
|
created_at: :time,
|
|
gitlab_version: :string
|
|
}.freeze
|
|
|
|
# Options used by the JSON parser
|
|
JSON_PARSE_OPTIONS = {
|
|
max_nesting: 1,
|
|
allow_nan: false,
|
|
symbolize_names: true
|
|
}.freeze
|
|
|
|
# Integer representing the increment of metadata version
|
|
# this data was saved with
|
|
# @return [Integer]
|
|
attr_reader :metadata_version
|
|
|
|
# Unique ID for a backup
|
|
# @return [String]
|
|
attr_reader :backup_id
|
|
|
|
# Timestamp when the backup was created
|
|
# @return [Time]
|
|
attr_reader :created_at
|
|
|
|
# Gitlab Version in which the backup was created
|
|
# @return [String]
|
|
attr_reader :gitlab_version
|
|
|
|
def initialize(
|
|
created_at:,
|
|
backup_id:,
|
|
gitlab_version:,
|
|
metadata_version: METADATA_VERSION
|
|
)
|
|
@metadata_version = metadata_version
|
|
@backup_id = backup_id
|
|
@created_at = created_at
|
|
@gitlab_version = gitlab_version
|
|
end
|
|
|
|
# Build a new BackupMetadata with defaults
|
|
#
|
|
# @param [String] gitlab_version
|
|
def self.build(gitlab_version:)
|
|
created_at = Time.current
|
|
backup_id = "#{created_at.strftime('%s_%Y_%m_%d_')}#{gitlab_version}"
|
|
|
|
new(
|
|
backup_id: backup_id,
|
|
created_at: created_at,
|
|
gitlab_version: gitlab_version
|
|
)
|
|
end
|
|
|
|
# Load the metadata from the JSON file stored in the given basepath
|
|
#
|
|
# @param [String|Pathname] basepath
|
|
# @return [Gitlab::Backup::Cli::Metadata::BackupMetadata, nil]
|
|
def self.load!(basepath)
|
|
basepath = Pathname(basepath) unless basepath.is_a? Pathname
|
|
|
|
json_file = basepath.join(METADATA_FILENAME)
|
|
json = JSON.parse(File.read(json_file), JSON_PARSE_OPTIONS)
|
|
deserializer = Gitlab::Backup::Cli::Metadata::Deserializer
|
|
|
|
parsed_fields = {}
|
|
METADATA_SCHEMA.each do |attribute_name, type|
|
|
stored_value = json[attribute_name]
|
|
parsed_value = deserializer.parse_value(type: type, value: stored_value)
|
|
|
|
parsed_fields[attribute_name] = parsed_value
|
|
end
|
|
|
|
new(**parsed_fields)
|
|
rescue IOError, Errno::ENOENT => e
|
|
Gitlab::Backup::Cli::Output.error(
|
|
"Failed to load backup information from: #{json_file} (#{e.message})"
|
|
)
|
|
|
|
nil
|
|
end
|
|
|
|
# Expose the information that will be part of the Metadata JSON file
|
|
def to_hash
|
|
serializer = Gitlab::Backup::Cli::Metadata::Serializer
|
|
|
|
METADATA_SCHEMA.each_with_object({}) do |(attribute_name, type), output|
|
|
# fetch attribute value dynamically
|
|
# rubocop:disable GitlabSecurity/PublicSend - we cant use read_attribute here, methods are already limited
|
|
value = public_send(attribute_name)
|
|
# rubocop:enable GitlabSecurity/PublicSend
|
|
serialized_value = serializer.serialize_value(type: type, value: value)
|
|
|
|
output[attribute_name] = serialized_value
|
|
end
|
|
end
|
|
|
|
# Write the metadata to a JSON file in the given basepath
|
|
#
|
|
# @param [String|Pathname] basepath
|
|
# @return [Boolean] whether successfully wrote to the disk
|
|
def write!(basepath)
|
|
basepath = Pathname(basepath) unless basepath.is_a? Pathname
|
|
|
|
json_file = basepath.join(METADATA_FILENAME)
|
|
json = JSON.pretty_generate(to_hash)
|
|
|
|
json_file.open(File::RDWR | File::CREAT, METADATA_FILE_MODE) do |file|
|
|
file.write(json)
|
|
end
|
|
|
|
true
|
|
rescue IOError, Errno::ENOENT => e
|
|
Gitlab::Backup::Cli::Output.error("Failed to Backup information to: #{json_file} (#{e.message})")
|
|
|
|
false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|