Skip to content

Instantly share code, notes, and snippets.

@imobachgs
Last active October 2, 2019 08:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imobachgs/3e4e3bc72e94d4c802bf31a26bd23a3b to your computer and use it in GitHub Desktop.
Save imobachgs/3e4e3bc72e94d4c802bf31a26bd23a3b to your computer and use it in GitHub Desktop.
# Copyright (c) [2019] 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 "yast"
module Yast2
module CFA
# This class reads/writes information through YaST2 agents
#
# It offers a File-like API (#read and #write methods) in order to read
# and write information using YaST2 agents.
#
# == Why?
#
# Usually, YaST2 agents contain the filename hardcoded in their definition (.scr files).
# So it is not possible to select a different file to read information from (like +/etc/modprobe.conf+,
# +/etc/modprobe.d/50-yast.conf+).
#
# Through this class, you can define the path on the fly. Agents are registered/unregistered as needed
# (FIXME: try to find out the performance penalty).
#
# @example Get +/etc/nsswitch.conf+ information from different sources.
# handler = CFA::Yast::AgentHandler.new(
# :ag_ini,
# :IniAgent,
# "options" => ["ignore_case", "global_values", "flat"],
# "comments" => ["^#.*", "^[ \t]*$"],
# "params" => [
# "match" => [ "^[ \t]*([a-zA-Z0-9_]+)[ \t]*:[ \t]*(.*[^ \t]|)[ \t]*$", "%s:\t%s" ]
# ]
# )
# handler.read("/etc/nsswitch.conf") #=> <Hash::...>
# handler.read("/etc/nsswitch.d/50-yast.conf") #=> <Hash::...>
#
# == TODO
#
# This is just a PoC but, there are somethings that we might need to address:
#
# * Read and writer are returning/expecting hashes. To mimic File behaviour, they should return
# a string which should be parsed by a CFA Parse. I am not sure whether it worths the
# conversion at all.
# * The CFA parser class is missing.
class AgentHandler
# Constructor
#
# @param agent [Symbol] Agent name (e.g., :ag_ini)
# @param source [Symbol] Agent source (e.g., :SysConfigFile, :IniFile, etc.)
# @param options [Hash<String,Array>] Agent options
def initialize(agent, source, options = {})
@agent = agent
@source = source
@options = options
end
# Reads the content from the agent
#
# @param [String] Filename
# @return [String] FIXME: string representation
def read(filename)
with_registered_agent(filename) do |scr_path|
keys = ::Yast::SCR.Dir(scr_path)
keys.each_with_object({}) do |key, all|
all[key] = ::Yast::SCR.Read("#{scr_path}.#{key}")
end
end
end
# Writes the content through the agent
#
# @param [String] filename
# @param [String] FIXME: file content
def write(filename, data)
with_registered_agent(filename) do |scr_path|
::Yast::SCR.Write(scr_path, data)
end
end
private
# Registers the agent and runs the given block of code
#
# The block receives the agent's path
#
# @param filename [String] File name to register the agent for
# @param block [Proc] Block to run
# @return [Object] Value returned by the block
def with_registered_agent(filename, &block)
scr_path = ::Yast::Path.new(".#{File.basename(filename)}")
::Yast::SCR.RegisterAgent(scr_path, agent_term(filename)) || raise("Cannot register agent #{scr_path}")
block.call(scr_path)
ensure
::Yast::SCR.UnregisterAgent(scr_path)
end
# Returns the term to define the agent
#
# @return [Yast::Term]
def agent_term(filename)
args = [@source, filename]
args << @options unless @options.empty?
::Yast.term(
@agent,
::Yast.term(*args)
)
end
end
end
end
file = Yast2::CFA::Sysconfig.new("/etc/sysconfig/keyboard")
file.load
puts file.inspect
class IdentityParser
attr_reader :empty
def initialize(empty)
@empty = empty
end
def serialize(data)
data
end
def parse(data)
data
end
end
module Yast2
module CFA
class Sysconfig < ::CFA::BaseModel
def initialize(path, options = {})
@path = path
parser = IdentityParser.new({})
file_handler = Yast2::CFA::AgentHandler.new(:ag_ini, :SysConfigFile, options)
load_handler = ::CFA::VendorLoader.new(
parser: parser,
file_handler: file_handler,
file_path: path
)
super(
parser, path, file_handler: file_handler, load_handler: load_handler
)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment