Class: BoxGrinder::Appliance

Inherits:
Object
  • Object
show all
Defined in:
lib/boxgrinder-build/appliance.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(appliance_definition, config = Config.new, options = {}) ⇒ Appliance

Returns a new instance of Appliance.



37
38
39
40
41
# File 'lib/boxgrinder-build/appliance.rb', line 37

def initialize(appliance_definition, config = Config.new, options = {})
  @appliance_definition = appliance_definition
  @config = config
  @log = options[:log] || LogHelper.new(:level => @config.log_level)
end

Instance Attribute Details

#appliance_configObject (readonly)

Returns the value of attribute appliance_config.



35
36
37
# File 'lib/boxgrinder-build/appliance.rb', line 35

def appliance_config
  @appliance_config
end

#plugin_chainObject (readonly)

Returns the value of attribute plugin_chain.



34
35
36
# File 'lib/boxgrinder-build/appliance.rb', line 34

def plugin_chain
  @plugin_chain
end

Instance Method Details

#createObject

This creates the appliance by executing the plugin chain.

Definition is read and validated. Afterwards a plugin chain is created and every plugin in the chain is initialized and validated. The next step is the execution of the plugin chain, step by step.

Below you can find the whole process of bootstrapping a plugin.

Call Scope

initialize required, internal init required, internal after_init optional, user implemented validate optional, user implemented after_validate optional, user implemented execute required, user implemented after_execute optional, user implemented



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/boxgrinder-build/appliance.rb', line 152

def create
  @log.debug "Launching new build..."
  @log.trace "Used configuration: #{@config.to_yaml.gsub(/(\S*(key|account|cert|username|host|password)\S*).*:(.*)/, '\1' + ": <REDACTED>")}"

  # Let's load all plugins first
  PluginHelper.new(@config, :log => @log).load_plugins
  read_definition
  validate_definition
  initialize_plugins

  remove_old_builds if @config.force

  execute_plugin_chain

  self
end

#delivery_selected?Boolean

Returns:

  • (Boolean)


173
174
175
# File 'lib/boxgrinder-build/appliance.rb', line 173

def delivery_selected?
  !(@config.delivery == :none or @config.delivery.to_s.empty? == nil)
end

#execute_plugin(plugin, param = nil) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/boxgrinder-build/appliance.rb', line 177

def execute_plugin(plugin, param = nil)
  if plugin.deliverables_exists?
    @log.info "Deliverables for #{plugin.plugin_info[:name]} #{plugin.plugin_info[:type]} plugin exists, skipping."
  else
    @log.debug "Executing #{plugin.plugin_info[:type]} plugin..."

    # Actually run the plugin
    param.nil? ? plugin.run : plugin.run(param)

    # Run after_execute callback, if implemented
    plugin.after_execute if plugin.respond_to?(:after_execute)

    @log.debug "#{plugin.plugin_info[:type].to_s.capitalize} plugin executed."
  end
end

#execute_plugin_chainObject



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/boxgrinder-build/appliance.rb', line 122

def execute_plugin_chain
  @log.info "Building '#{@appliance_config.name}' appliance for #{@appliance_config.hardware.arch} architecture."

  @plugin_chain.each do |p|
    if @config.change_to_user
      execute_with_userchange(p)
    else
      execute_without_userchange(p)
    end
  end
end

#initialize_plugin(plugin, plugin_info, options = {}) ⇒ Object

Initializes the plugin by executing init, after_init, validate and after_validate methods.

We can be sure only for init method because it is implemented internally in base-plugin.rb, for all other methods we need to check if they exist.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/boxgrinder-build/appliance.rb', line 88

def initialize_plugin(plugin, plugin_info, options = {})
  options = {
    :log => @log
  }.merge(options)

  unless @plugin_chain.empty?
    options.merge!(:previous_plugin => @plugin_chain.last[:plugin])
  end

  plugin.init(@config, @appliance_config, plugin_info, options)

  # Execute callbacks if implemented
  #
  # Order is very important
  [:after_init, :validate, :after_validate].each do |callback|
    plugin.send(callback) if plugin.respond_to?(callback)
  end

  param = nil

  # For operating system plugins we need to inject appliance definition.
  if plugin_info[:type] == :os
    param = @appliance_definition
  end

  @plugin_chain << {:plugin => plugin, :param => param}
end

#initialize_pluginsObject

Here we initialize all required plugins and create a plugin chain. Initialization involves also plugin configuration validation for specified plugin type.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/boxgrinder-build/appliance.rb', line 65

def initialize_plugins
  @plugin_chain = []

  os_plugin, os_plugin_info = PluginManager.instance.initialize_plugin(:os, @appliance_config.os.name.to_sym)
  initialize_plugin(os_plugin, os_plugin_info)

  if platform_selected?
    platform_plugin, platform_plugin_info = PluginManager.instance.initialize_plugin(:platform, @config.platform)
    initialize_plugin(platform_plugin, platform_plugin_info)
  end

  if delivery_selected?
    delivery_plugin, delivery_plugin_info = PluginManager.instance.initialize_plugin(:delivery, @config.delivery)
    # Here we need to specify additionally the type of the plugin, as some delivery plugins
    # can have multiple types of delivery implemented. See s3-plugin.rb for example.
    initialize_plugin(delivery_plugin, delivery_plugin_info, :type => @config.delivery)
  end
end

#platform_selected?Boolean

Returns:

  • (Boolean)


169
170
171
# File 'lib/boxgrinder-build/appliance.rb', line 169

def platform_selected?
  !(@config.platform == :none or @config.platform.to_s.empty? == nil)
end

#read_definitionObject

Raises:

  • (ValidationError)


43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/boxgrinder-build/appliance.rb', line 43

def read_definition
  appliance_helper = ApplianceDefinitionHelper.new(:log => @log)
  appliance_helper.read_definitions(@appliance_definition)

  appliance_configs = appliance_helper.appliance_configs
  appliance_config = appliance_configs.first

  raise ValidationError, "Ensure your appliance definition file has a '.appl' extension: #{File.basename(@appliance_definition)}." if appliance_config.nil?

  appliance_config_helper = ApplianceConfigHelper.new(appliance_configs)
  @appliance_config = appliance_config_helper.merge(appliance_config.clone.init_arch).initialize_paths
end

#remove_old_buildsObject



116
117
118
119
120
# File 'lib/boxgrinder-build/appliance.rb', line 116

def remove_old_builds
  @log.info "Removing previous builds for #{@appliance_config.name} appliance..."
  FileUtils.rm_rf(@appliance_config.path.build)
  @log.debug "Previous builds removed."
end

#validate_definitionObject



56
57
58
59
60
61
# File 'lib/boxgrinder-build/appliance.rb', line 56

def validate_definition
  os_plugin = PluginManager.instance.plugins[:os][@appliance_config.os.name.to_sym]

  raise "Unsupported operating system selected: #{@appliance_config.os.name}. Make sure you have installed right operating system plugin, see http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#Operating_system_plugins. Supported OSes are: #{PluginManager.instance.plugins[:os].keys.join(", ")}" if os_plugin.nil?
  raise "Unsupported operating system version selected: #{@appliance_config.os.version}. Supported versions are: #{os_plugin[:versions].join(", ")}" unless @appliance_config.os.version.nil? or os_plugin[:versions].include?(@appliance_config.os.version)
end