ref: refs/heads/basesystem
commit e7e556c48d5cb5190b6291fe298354ec60f982d9
Author: Duncan Mac-Vicar P
Date: Wed Aug 19 15:44:39 2009 +0200
- First version of the vendor settings API
Includes:
YaST::ConfigFile, a generic class for accessing a configuration file
from an arbitrary or predefined location
YaST::SettingsModel
A class that, based on ConfigFile, allows to quickly create an
ActiveRecord like model
VendorSetting
A concrete class based on SettingsModel
Plus tests, and docs
---
webservice/app/models/vendor_setting.rb | 23 ++++
webservice/lib/yast/config_file.rb | 124 ++++++++++++++++++++++
webservice/lib/yast/settings_model.rb | 78 ++++++++++++++
webservice/lib/yast/vendor_settings.rb | 20 ++++
webservice/test/unit/vendor_setting_test.rb | 42 ++++++++
webservice/test/unit/yast/config_file_test.rb | 34 ++++++
webservice/test/unit/yast/data/config/vendor.yml | 15 +++
webservice/test/unit/yast/settings_model_test.rb | 54 ++++++++++
8 files changed, 390 insertions(+), 0 deletions(-)
diff --git a/webservice/app/models/vendor_setting.rb b/webservice/app/models/vendor_setting.rb
new file mode 100644
index 0000000..950d08e
--- /dev/null
+++ b/webservice/app/models/vendor_setting.rb
@@ -0,0 +1,23 @@
+
+require 'yast/settings_model'
+
+# model representing the settings
+# in the vendor configuration file
+#
+# it can be used in two ways:
+#
+# settings = VendorSetting.find(:all)
+# settings.each do |setting|
+# setting.name
+# setting.value
+# end
+#
+# or accessing the setting directly:
+# VendorSetting.eula
+# => text
+#
+class VendorSetting < YaST::SettingsModel
+
+ config_name :vendor
+
+end
diff --git a/webservice/lib/yast/config_file.rb b/webservice/lib/yast/config_file.rb
new file mode 100644
index 0000000..391f7ee
--- /dev/null
+++ b/webservice/lib/yast/config_file.rb
@@ -0,0 +1,124 @@
+
+require 'yaml'
+
+module YaST
+ #
+ # Util class to read configuration
+ # files no matter what format they
+ # are
+ #
+ # Usage:
+ #
+ # To parse an arbitrary file:
+ # cfg = YaST::ConfigFile.new("/etc/somefile")
+ #
+ # To parse a file named myconfig.yml
+ # from the predefined location YaST::ConfigFile::CONFIG_DEFAULT_LOCATION
+ #
+ # cfg = YaST::ConfigFile.new(:loc)
+ # val = cfg[somekey][someotherkey]
+ #
+ # The extension will be determined automatically
+ #
+ # Supported formats are:
+ # * yaml
+ #
+ # If a resource or file is not found ConfigFile::NotFoundError is
+ # raised.
+ #
+ class ConfigFile
+ CONFIG_DEFAULT_LOCATION="/etc/YaST2"
+
+ # Error raised when a configuration file
+ # or resource is not found
+ class NotFoundError < RuntimeError
+ end
+
+ # initializes a config file based on
+ # a resource name or a file path
+ #
+ # if you specfy it using a symbol
+ # it will be searched in the default location
+ #
+ # otherwise the given path is used
+ def initialize(name)
+ @file_name = ConfigFile.resolve_file_name(name)
+ load_file(@file_name)
+ end
+
+ # access a key in the configuration
+ def [](key)
+ @data[key]
+ end
+
+ # modifies a key in the configuration
+ def []=(key, val)
+ @data[key] = val
+ end
+
+ # iterate over config keys and values
+ def each
+ @data.each do |key, val|
+ yield(key, val)
+ end
+ end
+
+ # true if configuration has a given key
+ def has_key?(name)
+ @data.has_key?(name)
+ end
+
+ # the file path where this config is operating on
+ def path
+ @file_name
+ end
+
+ # returns the xml representation if available
+ def to_xml
+ @data.to_xml
+ end
+
+ # resolves the file name
+ # and throws NotFoundError if
+ # it can't be resolved
+ def self.resolve_file_name(name)
+ file_name = name
+ if name.is_a?(Symbol)
+ file_name = File.join(config_default_location, "#{name}.yml")
+ end
+ # simple case first
+ raise NotFoundError if not File.exist?(file_name)
+ file_name
+ end
+
+ # returns the file content
+ def self.read_file(file_name)
+ File.open(file_name, 'r').read
+ end
+
+ # returns the file content
+ def read_file
+ ConfigFile.read_file(@file_name)
+ end
+
+ # loads data from a file and returns
+ # the data
+ def self.load_file(file_name)
+ YAML::load(read_file(file_name))
+ end
+
+ # loads data from a file
+ def load_file(file_name)
+ @data = ConfigFile.load_file(file_name)
+ end
+
+ # access the location constant
+ def self.config_default_location
+ # pattern that rails is following too
+ # see
+ # http://www.danielcadenas.com/2008/09/stubbingmocking-constants-with-mocha.ht...
+ CONFIG_DEFAULT_LOCATION
+ end
+
+ end
+end
diff --git a/webservice/lib/yast/settings_model.rb b/webservice/lib/yast/settings_model.rb
new file mode 100644
index 0000000..126e331
--- /dev/null
+++ b/webservice/lib/yast/settings_model.rb
@@ -0,0 +1,78 @@
+
+require 'yast/config_file'
+
+module YaST
+
+ # Base class for a model based on a
+ # config file with settings
+ #
+ # child classes need to reimplement
+ # config_name to let YaST::ConfigFile
+ # find the configuration
+ class SettingsModel
+
+ # initialize a model instance
+ def initialize(name, value)
+ SettingsModel.init
+ @name = name
+ @value = value
+ end
+
+ def self.path
+ SettingsModel.init
+ @@config.path
+ end
+
+ # find instances of the model
+ def self.find(what)
+ SettingsModel.init
+ ret = nil
+ if what == :all
+ ret = []
+ @@config.each do |key,val|
+ ret << self.new(key, val)
+ end
+ end
+ ret
+ end
+
+ def self.init
+ if not defined?(@@config)
+ @@config = YaST::ConfigFile.new(@@config_name)
+ end
+ end
+
+ def self.config_name(name)
+ @@config_name = name
+ end
+
+ # setting id, alias for name
+ def id
+ name
+ end
+
+ # setting name
+ def name
+ @name
+ end
+
+ def value
+ @value
+ end
+
+ def self.method_missing(name)
+ SettingsModel.init
+ # look if config has a key
+ if @@config.has_key?(name.to_s)
+ return @@config[name.to_s]
+ end
+ raise NoMethodError.new("undefined method `#{name}' for #{self.class.to_s}:Class")
+ end
+
+ def to_xml
+ tag_name = self.class.to_s.underscore
+ { :name => name, :value => value }.to_xml(:root => tag_name)
+ end
+ end
+
+end
diff --git a/webservice/lib/yast/vendor_settings.rb b/webservice/lib/yast/vendor_settings.rb
new file mode 100644
index 0000000..6fbb703
--- /dev/null
+++ b/webservice/lib/yast/vendor_settings.rb
@@ -0,0 +1,20 @@
+
+require 'yast/config_file'
+
+module YaST
+
+ # Vendor custom configuration of
+ # the host, located in /etc/YaST2/vendor.yml
+ class VendorSettings
+
+ def initialize
+ @config = ConfigFile.new(:vendor)
+ end
+
+ # eula that will be displayed
+ def eula
+ end
+
+ end
+
+end
diff --git a/webservice/test/unit/vendor_setting_test.rb b/webservice/test/unit/vendor_setting_test.rb
new file mode 100644
index 0000000..b1028d9
--- /dev/null
+++ b/webservice/test/unit/vendor_setting_test.rb
@@ -0,0 +1,42 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require 'vendor_setting'
+
+def test_data(name)
+ File.join(File.dirname(__FILE__), "data", name)
+end
+
+# example config file
+$config_data =<http://www.bugs.com
+packages:
+ - mydb-server
+ - mydb-console
+services:
+ - mydb-daemon
+ - syslog
+eula:
+ This is an evil eula that will
+ make you think twice before
+ clicking it
+EOF
+
+class VendorSettingTest < ActiveSupport::TestCase
+
+ def setup
+ YaST::ConfigFile.stubs(:resolve_file_name).with(:vendor).returns('/foo/vendor.yml')
+ YaST::ConfigFile.stubs(:read_file).with('/foo/vendor.yml').returns($config_data)
+ end
+
+ def test_config
+ settings = VendorSetting.find(:all)
+ # look for one setting
+ setting = settings.find{ |x| x.name == 'packages'}
+ assert_instance_of(Array, setting.value)
+ assert_equal("packages", setting.name)
+ assert_equal(4, settings.size)
+ assert_equal("http://www.bugs.com", VendorSetting.bug_url)
+ assert_instance_of(Array, VendorSetting.services)
+ assert_equal(2, VendorSetting.services.size)
+ end
+
+end
diff --git a/webservice/test/unit/yast/config_file_test.rb b/webservice/test/unit/yast/config_file_test.rb
new file mode 100644
index 0000000..ad16683
--- /dev/null
+++ b/webservice/test/unit/yast/config_file_test.rb
@@ -0,0 +1,34 @@
+require File.dirname(__FILE__) + '/../../test_helper'
+require 'yast/config_file'
+
+def test_data(name)
+ File.join(File.dirname(__FILE__), "data", name)
+end
+
+class ConfigFileTest < ActiveSupport::TestCase
+ def setup
+ YaST::ConfigFile.stubs(:config_default_location).returns(test_data('config'))
+ end
+
+ def test_config
+ # simple usage
+ config = YaST::ConfigFile.new(:vendor)
+
+ assert_equal(config.path, test_data('config/vendor.yml'))
+
+ assert_equal("This is an evil eula that will make you think twice before clicking it", config['appliance']['eula'])
+
+ # now try to load an non-existing resource
+ assert_raise YaST::ConfigFile::NotFoundError do
+ YaST::ConfigFile.new(:whatever)
+ end
+
+ # now try to load an non-existing file
+ assert_raise YaST::ConfigFile::NotFoundError do
+ YaST::ConfigFile.new(test_data('config/whatever.yml'))
+ end
+
+ #assert_instance_of Hash, config
+ end
+
+end
diff --git a/webservice/test/unit/yast/data/config/vendor.yml b/webservice/test/unit/yast/data/config/vendor.yml
new file mode 100644
index 0000000..496f997
--- /dev/null
+++ b/webservice/test/unit/yast/data/config/vendor.yml
@@ -0,0 +1,15 @@
+
+appliance:
+ bug_url: http://www.bugs.com
+ packages:
+ - mydb-server
+ - mydb-console
+ services:
+ - mydb-daemon
+ - syslog
+ eula:
+ This is an evil eula that will
+ make you think twice before
+ clicking it
+
+
diff --git a/webservice/test/unit/yast/settings_model_test.rb b/webservice/test/unit/yast/settings_model_test.rb
new file mode 100644
index 0000000..e7b8f48
--- /dev/null
+++ b/webservice/test/unit/yast/settings_model_test.rb
@@ -0,0 +1,54 @@
+
+require File.dirname(__FILE__) + '/../../test_helper'
+require 'yast/settings_model'
+
+def test_data(name)
+ File.join(File.dirname(__FILE__), "data", name)
+end
+
+# example config file
+$config_data =<