Class: Xolo::Core::BaseClasses::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/xolo/core/base_classes/configuration.rb

Overview

A class for working with pre-defined settings & preferences for Xolo

This is the base class for Xolo::Server::Configuration and Xolo::Admin::Configuration

The subclasses must ‘include Singleton’, making them use the Singleton Pattern, meaning only one instance can exist at a time.

This parent class provides methods for loading and saving YAML files with configuration and prefs settings in the Server or Admin context.

The YAML files store a Hash of keys and values relevent to the context they are used in.

Subclasses must define these constants and related methods:

Constant CONF_FILENAME [String]

The filename (not the full path) of the config yaml file to read and write.

Instance method #conf_file [Pathname]

The full expanded absolute path to the config yaml file.

Constant KEYS [HashHash]

The keys of this Hash are the keys that may be found in the yaml file.
The Hash values here define the value in the YAML file, with these keys:

  required: [Boolean] Is this key/value required in the YAML file? The server
     will not start if a required key is missing.

  type: [Symbol] The data-type of the value, one of the types supported by
    Optimist: :boolean, :string, :integer, :float, :io, :date
    See https://github.com/ManageIQ/optimist/wiki/Option-Types

  default: [Object] If this key doesn't exist in the YAML file, this is the
    value used by Xolo.

  desc: [String] A full description of what this value is, how it is used,
    possible values, etc. This is presented in help and/or walkthru.

  load_method: [Symbol] The name of a method in the Configuration Instance
    to which the YAML value will be passed to convert it into the real value
    to be used.  For example, some YAML values might contain a command to be
    executed, a pathname to be read, or a raw value to be used. These
    values should be passed to the :data_from_command_file_or_string method
    which will return the value to actually be used (the stdout of a command,
    the contents of a file, or a raw value)

  private: [Boolean] If true, the value is never presented in logs or normal
    output. it is replaced with <private>. Use this for sensitive secrets.

Direct Known Subclasses

Server::Configuration

Constant Summary collapse

PIPE =

Constants

'|'
PRIVATE =
'<private>'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

# Initialize!



102
103
104
105
# File 'lib/xolo/core/base_classes/configuration.rb', line 102

def initialize
  keys.each_key { |attr| self.class.attr_accessor attr }
  load_from_file
end

Instance Attribute Details

#raw_dataHash{Symbol: Object} (readonly)

Returns The data as read directly from the YAML file.

Returns:

  • (Hash{Symbol: Object})

    The data as read directly from the YAML file



93
94
95
# File 'lib/xolo/core/base_classes/configuration.rb', line 93

def raw_data
  @raw_data
end

Class Method Details

.inherited(child_class) ⇒ Object

Class Methods



84
85
86
# File 'lib/xolo/core/base_classes/configuration.rb', line 84

def self.inherited(child_class)
  Xolo.verbose_inherit child_class, self
end

Instance Method Details

#data_from_command_file_or_string(str, enforce_secure_mode: false) ⇒ String

If the given string starts with a pipe (|) then remove the pipe and execute the remainder, returning its stdout.

If the given string is a path to an executable file path, return its stdout.

If the given string is a path to a readable file path, return its contents.

Otherwise, the string is the desired data, so just return it.

Parameters:

  • str (String)

    a command, file path, or string

  • enforce_secure_mode (Boolean) (defaults to: false)

    If true, and the str is a path to a file, make sure that the file mode is 700 or 600.

Returns:

  • (String)

    The std output of the command, file contents, or string



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/xolo/core/base_classes/configuration.rb', line 165

def data_from_command_file_or_string(str, enforce_secure_mode: false)
  # if it starts with a pipe, it's a command and args
  # remove the pipe and execute the rest, returning stdout
  return `#{str.delete_prefix(PIPE)}`.chomp if str.start_with? PIPE

  path = Pathname.new(str)
  return str unless path.file?

  # this will return, e.g. "600" "775" etc as strings
  mode = format '%o', (path.stat.mode & 0o777)

  if path.executable?
    if enforce_secure_mode && !mode.end_with?('00')
      raise Xolo::Core::Exceptions::PermissionError,
            "Executable file #{str} must be mode 0700, 0500, or 0100"
    end
    `#{path.to_s.shellescape}`.chomp

  elsif path.readable?
    if enforce_secure_mode && mode != '600'
      raise Xolo::Core::Exceptions::PermissionError,
            "Readable file #{str} must be mode 0600"
    end
    path.read.chomp

  else
    str
  end
end

#save_to_file(data: nil) ⇒ void

This method returns an undefined value.

Save new data (or raw_data) to the config file. We don’t save the actual instance variables, as they may be expanded from commands or file paths, and its the commands or file paths we want to save.

Parameters:

  • data (Hash{Symbol: Object}) (defaults to: nil)

    The data to save to the config file



138
139
140
141
142
143
# File 'lib/xolo/core/base_classes/configuration.rb', line 138

def save_to_file(data: nil)
  data ||= raw_data
  conf_file.parent.mkpath unless conf_file.parent.directory?
  conf_file.pix_save YAML.dump(data)
  conf_file.chmod 0o600
end

#to_hObject



112
113
114
115
116
117
118
# File 'lib/xolo/core/base_classes/configuration.rb', line 112

def to_h
  data = {}
  keys.each_key do |key|
    data[key] = send(key)
  end
  data
end

#to_h_privateObject



121
122
123
124
125
126
127
# File 'lib/xolo/core/base_classes/configuration.rb', line 121

def to_h_private
  data = to_h
  keys.each do |key, deets|
    data[key] = PRIVATE if deets[:private]
  end
  data
end