Skip to content

Commit

Permalink
storage: make conversions reusable
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Sep 10, 2024
1 parent 9ba3f55 commit 1582a5c
Show file tree
Hide file tree
Showing 23 changed files with 1,041 additions and 507 deletions.
111 changes: 111 additions & 0 deletions service/lib/agama/storage/config_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "agama/storage/configs"
require "agama/storage/proposal_settings_reader"
require "agama/storage/volume_templates_builder"

module Agama
module Storage
# Class for building configs.
class ConfigBuilder
# @todo Replace product_config param by a ProductDefinition.
#
# @param product_config [Agama::Config]
def initialize(product_config)
@product_config = product_config
end

# Default drive config from the product definition.
#
# @param path [String, nil]
# @return [Configs::Drive]
def default_drive(path = nil)
Configs::Drive.new.tap do |drive|
drive.encryption = default_encryption
drive.filesystem = default_filesystem(path)
end
end

# Default partition config from the product definition.
#
# @param path [String, nil]
# @return [Configs::Partition]
def default_partition(path = nil)
Configs::Partition.new.tap do |partition|
partition.encryption = default_encryption
partition.filesystem = default_filesystem(path)
end
end

private

# @return [Agama::Config]
attr_reader :product_config

# Default encryption config from the product definition.
#
# @return [Configs::Encryption]
def default_encryption
Configs::Encryption.new.tap do |config|
config.password = settings.encryption.password
config.method = settings.encryption.method
config.pbkd_function = settings.encryption.pbkd_function
end
end

# Default format config from the product definition.
#
# @param path [String, nil]
# @return [Configs::Filesystem]
def default_filesystem(path = nil)
path ||= ""

Configs::Filesystem.new.tap do |config|
config.type = default_fstype(path)
end
end

# Default filesystem type config from the product definition.
#
# @param path [String]
# @return [Configs::FilesystemType]
def default_fstype(path = nil)
volume = volume_builder.for(path || "")

Configs::FilesystemType.new.tap do |config|
config.fs_type = volume.fs_type
config.btrfs = volume.btrfs
end
end

# @return [ProposalSettings]
def settings
@settings ||= ProposalSettingsReader.new(product_config).read
end

# @return [VolumeTemplatesBuilder]
def volume_builder
@volume_builder ||= VolumeTemplatesBuilder.new_from_config(product_config)
end
end
end
end
74 changes: 13 additions & 61 deletions service/lib/agama/storage/config_conversions/from_json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,14 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "agama/storage/config"
require "agama/storage/config_conversions/from_json_conversions/drive"
require "agama/storage/configs/boot"
require "agama/storage/proposal_settings_reader"
require "agama/storage/config_builder"
require "agama/storage/config_conversions/from_json_conversions/config"
require "agama/storage/volume_templates_builder"

module Agama
module Storage
module ConfigConversions
# Config conversion from JSON hash according to schema.
#
# TODO: The approach for generating a Config from JSON could be improved:
# * All the FromJSON classes receive only a JSON and an optional default config to start
# converting from it.
# * There should be a "config generator" class which knows the ProductDefinition and creates
# config objects calling to the proper FromJSON classes, passing the default config for
# each case (drive, partition, etc).
#
# For example:
#
# def generate_drive(drive_json)
# default = default_drive(drive_json.dig(:filesystem, :path))
# drive = Drive::FromJson.new(drive_json).convert(default)
# drive.partitions = drive_json[:partitions].map do |partition_json|
# default = default_partition(partition_json.dig(:fileystem, :path))
# Partition::FromJSON.new(partition_json).convert(default)
# end
# drive
# end
#
# This improvement could be done at the time of introducing the ProductDefinition class.
class FromJSON
# @todo Replace product_config param by a ProductDefinition.
#
Expand All @@ -61,17 +39,16 @@ def initialize(config_json, product_config:)

# Performs the conversion from Hash according to the JSON schema.
#
# @todo Raise error if config_json does not match the JSON schema.
#
# @return [Storage::Config]
def convert
# @todo Raise error if config_json does not match the JSON schema.
Storage::Config.new.tap do |config|
boot = convert_boot
drives = convert_drives
config = FromJSONConversions::Config
.new(config_json, config_builder: config_builder)
.convert

config.boot = boot if boot
config.drives = drives if drives
config.calculate_default_sizes(volume_builder)
end
config.calculate_default_sizes(volume_builder)
config
end

private
Expand All @@ -82,34 +59,9 @@ def convert
# @return [Agama::Config]
attr_reader :product_config

# @return [Configs::Boot, nil]
def convert_boot
boot_json = config_json[:boot]
return unless boot_json

Configs::Boot.new.tap do |config|
config.configure = boot_json[:configure]
config.device = boot_json[:device]
end
end

# @return [Array<Configs::Drive>, nil]
def convert_drives
drives_json = config_json[:drives]
return unless drives_json

drives_json.map { |d| convert_drive(d) }
end

# @return [Configs::Drive]
def convert_drive(drive_json)
FromJSONConversions::Drive.new(drive_json,
settings: settings, volume_builder: volume_builder).convert
end

# @return [ProposalSettings]
def settings
@settings ||= ProposalSettingsReader.new(product_config).read
# @return [ConfigBuilder]
def config_builder
@config_builder ||= ConfigBuilder.new(product_config)
end

# @return [VolumeTemplatesBuilder]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "agama/storage/config_conversions/from_json_conversions/boot"
require "agama/storage/config_conversions/from_json_conversions/block_device"
require "agama/storage/config_conversions/from_json_conversions/btrfs"
require "agama/storage/config_conversions/from_json_conversions/config"
require "agama/storage/config_conversions/from_json_conversions/drive"
require "agama/storage/config_conversions/from_json_conversions/encryption"
require "agama/storage/config_conversions/from_json_conversions/filesystem"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "agama/storage/configs/drive"
require "agama/storage/configs/partition"

module Agama
module Storage
module ConfigConversions
module FromJSONConversions
# Base class for conversions from JSON hash according to schema.
class Base
# @param config_builder [ConfigBuilder, nil]
def initialize(config_builder = nil)
@config_builder = config_builder
end

# Performs the conversion from Hash according to the JSON schema.
#
# @param default [Object] Any config from {Storage::Configs}.
# @return [Object] Any config from {Storage::Configs}.
def convert(default)
default.dup.tap do |config|
conversions(config).each do |property, value|
next if skip?(property, value)

config.public_send("#{property}=", value)
end
end
end

private

# @return [ConfigBuilder, nil]
attr_reader :config_builder

# Values to apply to the config.
#
# @param _default [Object] Any config from {Storage::Configs}.
# @return [Hash] e.g., { name: "/dev/vda" }.
def conversions(_default)
{}
end

# Whether to skip the assignment of the property.
#
# @param _property [Symbol]
# @param value [Object]
# @return [Boolean]
def skip?(_property, value)
value.nil?
end
end
end
end
end
end
Loading

0 comments on commit 1582a5c

Please sign in to comment.