boxgrinder-core 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +10 -0
- data/Rakefile +13 -9
- data/boxgrinder-core.gemspec +11 -8
- data/lib/boxgrinder-core/appliance-parser.rb +84 -0
- data/{spec/validators/appliance-config-validator-spec.rb → lib/boxgrinder-core/appliance-validator.rb} +15 -2
- data/lib/boxgrinder-core/{validators/errors.rb → errors.rb} +16 -0
- data/lib/boxgrinder-core/helpers/appliance-config-helper.rb +10 -18
- data/lib/boxgrinder-core/helpers/appliance-definition-helper.rb +19 -59
- data/lib/boxgrinder-core/helpers/appliance-transformation-helper.rb +58 -0
- data/lib/boxgrinder-core/helpers/exec-helper.rb +48 -21
- data/lib/boxgrinder-core/models/appliance-config.rb +39 -23
- data/lib/boxgrinder-core/models/config.rb +4 -2
- data/lib/boxgrinder-core/schemas/appliance_schema_0.8.0.yaml +95 -0
- data/lib/boxgrinder-core/schemas/appliance_schema_0.9.0.yaml +92 -0
- data/rubygem-boxgrinder-core.spec +13 -1
- data/spec/appliance-parser-spec.rb +68 -0
- data/spec/appliance-validator-spec.rb +71 -0
- data/spec/helpers/appliance-config-helper-spec.rb +136 -1
- data/spec/helpers/appliance-definition-helper-spec.rb +51 -79
- data/spec/helpers/appliance-transformation-helper-spec.rb +51 -0
- data/spec/helpers/exec-helper-spec.rb +40 -12
- data/spec/helpers/log-helper-spec.rb +1 -0
- data/spec/models/config-spec.rb +2 -1
- data/spec/rspec/src/appliances/0.8.x.appl +38 -0
- data/spec/rspec/src/appliances/0.9.x-invalid.appl +40 -0
- data/spec/rspec/src/appliances/0.9.x.appl +36 -0
- metadata +48 -19
- data/lib/boxgrinder-core/validators/appliance-config-validator.rb +0 -65
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
v0.3.1
|
2
|
+
|
3
|
+
* [BGBUILD-164] Guestfs writes to /tmp/ by default, potentially filling the root filesystem
|
4
|
+
* [BGBUILD-97] some filesystems dont get unmounted on BG interruption
|
5
|
+
* [BGBUILD-155] Images built on Centos5.x (el5) for VirtualBox kernel panic (/dev/root missing)
|
6
|
+
* [BGBUILD-190] Allow to specify kernel variant (PAE or not) for Fedora OS
|
7
|
+
* [BGBUILD-192] Use IO.popen4 instead open4 gem on JRuby
|
8
|
+
* [BGBUILD-198] root password is not inherited
|
9
|
+
* [BGBUILD-156] Validate appliance definition files early and return meaningful error messages
|
10
|
+
|
1
11
|
v0.3.0
|
2
12
|
|
3
13
|
* [BGBUILD-178] Remove sensitive data from logs
|
data/Rakefile
CHANGED
@@ -17,19 +17,24 @@
|
|
17
17
|
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
18
|
|
19
19
|
require 'rubygems'
|
20
|
-
|
20
|
+
|
21
|
+
begin
|
22
|
+
require 'rake/dsl'
|
23
|
+
rescue LoadError
|
24
|
+
end
|
25
|
+
|
21
26
|
require 'echoe'
|
22
27
|
|
23
28
|
Echoe.new("boxgrinder-core") do |p|
|
24
|
-
p.project
|
25
|
-
p.author
|
26
|
-
p.summary
|
27
|
-
p.url
|
28
|
-
p.email
|
29
|
-
p.runtime_dependencies = ['
|
29
|
+
p.project = "BoxGrinder"
|
30
|
+
p.author = "Marek Goldmann"
|
31
|
+
p.summary = "Core library for BoxGrinder"
|
32
|
+
p.url = "http://boxgrinder.org"
|
33
|
+
p.email = "info@boxgrinder.org"
|
34
|
+
p.runtime_dependencies = ['hashery >=1.3.0', 'kwalify >=0.7.2']
|
35
|
+
p.runtime_dependencies << 'open4 >=1.0.0' unless RUBY_PLATFORM =~ /java/
|
30
36
|
end
|
31
37
|
|
32
|
-
desc "Run all tests"
|
33
38
|
Spec::Rake::SpecTask.new('spec') do |t|
|
34
39
|
t.rcov = false
|
35
40
|
t.spec_files = FileList["spec/**/*-spec.rb"]
|
@@ -37,7 +42,6 @@ Spec::Rake::SpecTask.new('spec') do |t|
|
|
37
42
|
t.verbose = true
|
38
43
|
end
|
39
44
|
|
40
|
-
desc "Run all tests and generate code coverage report"
|
41
45
|
Spec::Rake::SpecTask.new('spec:coverage') do |t|
|
42
46
|
t.spec_files = FileList["spec/**/*-spec.rb"]
|
43
47
|
t.spec_opts = ['--colour', '--format', 'html:pkg/rspec_report.html', '-b']
|
data/boxgrinder-core.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{boxgrinder-core}
|
5
|
-
s.version = "0.3.
|
5
|
+
s.version = "0.3.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Marek Goldmann"]
|
9
|
-
s.date = %q{2011-
|
9
|
+
s.date = %q{2011-04-27}
|
10
10
|
s.description = %q{Core library for BoxGrinder}
|
11
11
|
s.email = %q{info@boxgrinder.org}
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/boxgrinder-core.rb", "lib/boxgrinder-core/helpers/appliance-config-helper.rb", "lib/boxgrinder-core/helpers/appliance-definition-helper.rb", "lib/boxgrinder-core/helpers/exec-helper.rb", "lib/boxgrinder-core/helpers/log-helper.rb", "lib/boxgrinder-core/models/appliance-config.rb", "lib/boxgrinder-core/models/config.rb", "lib/boxgrinder-core/models/task.rb", "lib/boxgrinder-core/
|
13
|
-
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "boxgrinder-core.gemspec", "lib/boxgrinder-core.rb", "lib/boxgrinder-core/helpers/appliance-config-helper.rb", "lib/boxgrinder-core/helpers/appliance-definition-helper.rb", "lib/boxgrinder-core/helpers/exec-helper.rb", "lib/boxgrinder-core/helpers/log-helper.rb", "lib/boxgrinder-core/models/appliance-config.rb", "lib/boxgrinder-core/models/config.rb", "lib/boxgrinder-core/models/task.rb", "lib/boxgrinder-core/
|
14
|
-
s.homepage = %q{http://
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/boxgrinder-core.rb", "lib/boxgrinder-core/appliance-parser.rb", "lib/boxgrinder-core/appliance-validator.rb", "lib/boxgrinder-core/errors.rb", "lib/boxgrinder-core/helpers/appliance-config-helper.rb", "lib/boxgrinder-core/helpers/appliance-definition-helper.rb", "lib/boxgrinder-core/helpers/appliance-transformation-helper.rb", "lib/boxgrinder-core/helpers/exec-helper.rb", "lib/boxgrinder-core/helpers/log-helper.rb", "lib/boxgrinder-core/models/appliance-config.rb", "lib/boxgrinder-core/models/config.rb", "lib/boxgrinder-core/models/task.rb", "lib/boxgrinder-core/schemas/appliance_schema_0.8.0.yaml", "lib/boxgrinder-core/schemas/appliance_schema_0.9.0.yaml"]
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "boxgrinder-core.gemspec", "lib/boxgrinder-core.rb", "lib/boxgrinder-core/appliance-parser.rb", "lib/boxgrinder-core/appliance-validator.rb", "lib/boxgrinder-core/errors.rb", "lib/boxgrinder-core/helpers/appliance-config-helper.rb", "lib/boxgrinder-core/helpers/appliance-definition-helper.rb", "lib/boxgrinder-core/helpers/appliance-transformation-helper.rb", "lib/boxgrinder-core/helpers/exec-helper.rb", "lib/boxgrinder-core/helpers/log-helper.rb", "lib/boxgrinder-core/models/appliance-config.rb", "lib/boxgrinder-core/models/config.rb", "lib/boxgrinder-core/models/task.rb", "lib/boxgrinder-core/schemas/appliance_schema_0.8.0.yaml", "lib/boxgrinder-core/schemas/appliance_schema_0.9.0.yaml", "rubygem-boxgrinder-core.spec", "spec/appliance-parser-spec.rb", "spec/appliance-validator-spec.rb", "spec/helpers/appliance-config-helper-spec.rb", "spec/helpers/appliance-definition-helper-spec.rb", "spec/helpers/appliance-transformation-helper-spec.rb", "spec/helpers/exec-helper-spec.rb", "spec/helpers/log-helper-spec.rb", "spec/models/config-spec.rb", "spec/rspec/ls/one", "spec/rspec/ls/two", "spec/rspec/src/appliances/0.8.x.appl", "spec/rspec/src/appliances/0.9.x-invalid.appl", "spec/rspec/src/appliances/0.9.x.appl", "spec/rspec/src/appliances/ephemeral-repo.appl", "spec/rspec/src/appliances/full.appl", "spec/rspec/src/appliances/invalid-yaml.appl", "spec/rspec/src/appliances/legacy.appl", "spec/rspec/src/appliances/repo.appl", "spec/rspec/src/config/empty", "spec/rspec/src/config/valid"]
|
14
|
+
s.homepage = %q{http://boxgrinder.org}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Boxgrinder-core", "--main", "README"]
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = %q{BoxGrinder}
|
@@ -23,14 +23,17 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.specification_version = 3
|
24
24
|
|
25
25
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
-
s.add_runtime_dependency(%q<open4>, [">= 1.0.0"])
|
27
26
|
s.add_runtime_dependency(%q<hashery>, [">= 1.3.0"])
|
27
|
+
s.add_runtime_dependency(%q<kwalify>, [">= 0.7.2"])
|
28
|
+
s.add_runtime_dependency(%q<open4>, [">= 1.0.0"])
|
28
29
|
else
|
29
|
-
s.add_dependency(%q<open4>, [">= 1.0.0"])
|
30
30
|
s.add_dependency(%q<hashery>, [">= 1.3.0"])
|
31
|
+
s.add_dependency(%q<kwalify>, [">= 0.7.2"])
|
32
|
+
s.add_dependency(%q<open4>, [">= 1.0.0"])
|
31
33
|
end
|
32
34
|
else
|
33
|
-
s.add_dependency(%q<open4>, [">= 1.0.0"])
|
34
35
|
s.add_dependency(%q<hashery>, [">= 1.3.0"])
|
36
|
+
s.add_dependency(%q<kwalify>, [">= 0.7.2"])
|
37
|
+
s.add_dependency(%q<open4>, [">= 1.0.0"])
|
35
38
|
end
|
36
39
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'kwalify'
|
20
|
+
require 'boxgrinder-core/helpers/appliance-transformation-helper'
|
21
|
+
require 'boxgrinder-core/helpers/log-helper'
|
22
|
+
require 'boxgrinder-core/appliance-validator'
|
23
|
+
require 'boxgrinder-core/errors'
|
24
|
+
|
25
|
+
module BoxGrinder
|
26
|
+
class ApplianceParser
|
27
|
+
def initialize(options = {})
|
28
|
+
@log = options[:log] || LogHelper.new
|
29
|
+
@schemas = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_schemas
|
33
|
+
Dir.glob("#{File.dirname(__FILE__)}/schemas/{*.yaml,*.yml}").each do |f|
|
34
|
+
schema = Kwalify::Yaml.load_file(f)
|
35
|
+
@schemas[schema['version']] = schema
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_definition(appliance_definition, file = true)
|
40
|
+
if file
|
41
|
+
@log.info "Validating appliance definition from #{appliance_definition} file..."
|
42
|
+
appliance_definition = File.read(appliance_definition)
|
43
|
+
else
|
44
|
+
@log.info "Validating appliance definition from string..."
|
45
|
+
end
|
46
|
+
|
47
|
+
failures = {}
|
48
|
+
schema_versions = @schemas.keys.sort.reverse
|
49
|
+
|
50
|
+
schema_versions.each do |schema_version|
|
51
|
+
@schemas[schema_version].delete('version')
|
52
|
+
appliance_config, errors = parse(@schemas[schema_version], appliance_definition)
|
53
|
+
|
54
|
+
if errors.empty?
|
55
|
+
@log.info "Appliance definition is valid."
|
56
|
+
return ApplianceTransformationHelper.new(schema_versions.first, :log => @log).transform(appliance_config, schema_version)
|
57
|
+
end
|
58
|
+
|
59
|
+
failures[schema_version] = errors
|
60
|
+
end
|
61
|
+
|
62
|
+
# If all schemas fail then we assume they are using the latest schema..
|
63
|
+
failures[schema_versions.first].each do |error|
|
64
|
+
@log.error "Error: [line #{error.linenum}, col #{error.column}] [#{error.path}] #{error.message}"
|
65
|
+
end
|
66
|
+
|
67
|
+
raise ApplianceValidationError, "The appliance definition was invalid according to schema #{schema_versions.first}. See log for details."
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse(schema_document, appliance_definition)
|
71
|
+
validator = ApplianceValidator.new(schema_document)
|
72
|
+
parser = Kwalify::Yaml::Parser.new(validator)
|
73
|
+
|
74
|
+
begin
|
75
|
+
parsed = parser.parse(appliance_definition)
|
76
|
+
rescue Kwalify::KwalifyError => e
|
77
|
+
raise ApplianceValidationError, "The appliance definition couldn't be parsed. [line #{e.linenum}, col #{e.column}] [#{e.path}] Most probably you try to specify partition mount point starting with backslash (/), please quote it like this: \"/foo\"." if e.message =~ /document end expected \(maybe invalid tab char found\)/
|
78
|
+
raise ApplianceValidationError, "The appliance definition couldn't be parsed. #{e}"
|
79
|
+
end
|
80
|
+
|
81
|
+
[parsed, parser.errors]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -16,9 +16,22 @@
|
|
16
16
|
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
17
|
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
18
|
|
19
|
-
require '
|
19
|
+
require 'kwalify'
|
20
|
+
require 'boxgrinder-core/helpers/log-helper'
|
20
21
|
|
21
22
|
module BoxGrinder
|
22
|
-
|
23
|
+
class ApplianceValidator < Kwalify::Validator
|
24
|
+
def initialize(schema)
|
25
|
+
super(schema) # Super constructor
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_hook(value, rule, path, errors)
|
29
|
+
case rule.name
|
30
|
+
when 'Repository' # enforce baseurl xor mirrorlist
|
31
|
+
errors << Kwalify::ValidationError.new("Please specify either a baseurl or a mirrorlist.", path) unless value['baseurl'].nil? ^ value['mirrorlist'].nil?
|
32
|
+
when 'Hardware' # enforce multiple of 64
|
33
|
+
errors << Kwalify::ValidationError.new("Specified memory amount: #{value['memory']} is invalid. The value must be a multiple of 64.", path) unless value['memory'].nil? or value['memory']%64==0
|
34
|
+
end
|
35
|
+
end
|
23
36
|
end
|
24
37
|
end
|
@@ -24,6 +24,22 @@ module BoxGrinder
|
|
24
24
|
class ApplianceValidationError < ValidationError
|
25
25
|
|
26
26
|
end
|
27
|
+
|
28
|
+
class SchemaValidationError < ValidationError
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class PluginValidationError < ValidationError
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class UnknownFormatError < ValidationError
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class PluginError < StandardError
|
41
|
+
|
42
|
+
end
|
27
43
|
end
|
28
44
|
|
29
45
|
class StandardError
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
17
|
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
18
|
|
19
|
-
require 'boxgrinder-core/
|
19
|
+
require 'boxgrinder-core/errors'
|
20
20
|
require 'set'
|
21
21
|
|
22
22
|
module BoxGrinder
|
@@ -80,7 +80,7 @@ module BoxGrinder
|
|
80
80
|
resolve_stack.index(k).nil?
|
81
81
|
}
|
82
82
|
refs.each do |ref|
|
83
|
-
resolve(
|
83
|
+
resolve(Array.new(resolve_stack).push(ref), resolved_set) unless resolved_set.include?(ref)
|
84
84
|
while @appliance_config.variables[var].include? "##{ref}#" do
|
85
85
|
@appliance_config.variables[var].gsub!("##{ref}#", @appliance_config.variables[ref])
|
86
86
|
end
|
@@ -112,7 +112,7 @@ module BoxGrinder
|
|
112
112
|
partitions[root].delete('options') if partitions[root]['type'] != partition['type']
|
113
113
|
partitions[root]['type'] = partition['type']
|
114
114
|
else
|
115
|
-
partitions[root]['type'] = default_filesystem_type
|
115
|
+
partitions[root]['type'] = @appliance_config.default_filesystem_type
|
116
116
|
end
|
117
117
|
else
|
118
118
|
partitions[root] = {}
|
@@ -121,7 +121,7 @@ module BoxGrinder
|
|
121
121
|
unless partition['type'].nil?
|
122
122
|
partitions[root]['type'] = partition['type']
|
123
123
|
else
|
124
|
-
partitions[root]['type'] = default_filesystem_type
|
124
|
+
partitions[root]['type'] = @appliance_config.default_filesystem_type
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -130,21 +130,10 @@ module BoxGrinder
|
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
def default_filesystem_type
|
137
|
-
fs = 'ext4'
|
138
|
-
|
139
|
-
case @appliance_config.os.name
|
140
|
-
when 'rhel', 'centos'
|
141
|
-
case @appliance_config.os.version
|
142
|
-
when '5'
|
143
|
-
fs = 'ext3'
|
144
|
-
end
|
145
|
-
end
|
133
|
+
# https://bugzilla.redhat.com/show_bug.cgi?id=466275
|
134
|
+
partitions['/boot'] = {'type' => 'ext3', 'size' => 0.1} if partitions['/boot'].nil? and (@appliance_config.os.name == 'centos' or @appliance_config.os.name == 'rhel') and @appliance_config.os.version == '5'
|
146
135
|
|
147
|
-
|
136
|
+
@appliance_config.hardware.partitions = partitions
|
148
137
|
end
|
149
138
|
|
150
139
|
def merge_memory
|
@@ -155,6 +144,9 @@ module BoxGrinder
|
|
155
144
|
merge_field('os.name') { |name| @appliance_config.os.name = name.to_s }
|
156
145
|
merge_field('os.version') { |version| @appliance_config.os.version = version.to_s }
|
157
146
|
merge_field('os.password') { |password| @appliance_config.os.password = password.to_s }
|
147
|
+
merge_field('os.pae') { |pae| @appliance_config.os.pae = false unless pae }
|
148
|
+
|
149
|
+
@appliance_config.os.password = 'boxgrinder' if @appliance_config.os.password.nil?
|
158
150
|
end
|
159
151
|
|
160
152
|
def prepare_appliances
|
@@ -16,40 +16,38 @@
|
|
16
16
|
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
17
|
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
18
|
|
19
|
+
require 'boxgrinder-core/helpers/log-helper'
|
19
20
|
require 'boxgrinder-core/models/appliance-config'
|
20
|
-
require '
|
21
|
+
require 'boxgrinder-core/appliance-parser'
|
21
22
|
|
22
23
|
module BoxGrinder
|
23
24
|
class ApplianceDefinitionHelper
|
24
25
|
def initialize(options = {})
|
25
|
-
@log = options[:log] ||
|
26
|
+
@log = options[:log] || LogHelper.new
|
26
27
|
@appliance_configs = []
|
28
|
+
@appliance_parser = ApplianceParser.new(:log => @log)
|
27
29
|
end
|
28
30
|
|
29
31
|
attr_reader :appliance_configs
|
32
|
+
attr_reader :appliance_parser
|
30
33
|
|
31
34
|
# Reads definition provided as string. This string can be a YAML document. In this case
|
32
35
|
# definition is parsed and an ApplianceConfig object is returned. In other cases it tries to search
|
33
36
|
# for a file with provided name.
|
34
37
|
def read_definitions(definition, content_type = nil)
|
38
|
+
@appliance_parser.load_schemas
|
35
39
|
if File.exists?(definition)
|
36
|
-
@log.debug "Reading definition from '#{definition}' file..."
|
37
|
-
|
38
40
|
definition_file_extension = File.extname(definition)
|
39
41
|
|
40
42
|
appliance_config =
|
41
43
|
case definition_file_extension
|
42
44
|
when '.appl', '.yml', '.yaml'
|
43
|
-
|
44
|
-
when '.xml'
|
45
|
-
read_xml_file(definition)
|
45
|
+
parse_yaml(@appliance_parser.parse_definition(definition))
|
46
46
|
else
|
47
47
|
unless content_type.nil?
|
48
48
|
case content_type
|
49
49
|
when 'application/x-yaml', 'text/yaml'
|
50
|
-
|
51
|
-
when 'application/xml', 'text/xml', 'application/x-xml'
|
52
|
-
read_xml_file(definition)
|
50
|
+
parse_yaml(@appliance_parser.parse_definition(definition))
|
53
51
|
end
|
54
52
|
end
|
55
53
|
end
|
@@ -65,35 +63,12 @@ module BoxGrinder
|
|
65
63
|
read_definitions("#{File.dirname(definition)}/#{appliance_name}#{definition_file_extension}") unless appliances.include?(appliance_name)
|
66
64
|
end unless appliance_config.appliances.nil? or !appliance_config.appliances.is_a?(Array)
|
67
65
|
else
|
68
|
-
|
69
|
-
|
70
|
-
@appliance_configs << read_yaml(definition)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def read_yaml(content)
|
75
|
-
begin
|
76
|
-
definition = YAML.load(content)
|
77
|
-
raise "Not a valid YAML content." if definition.nil? or definition == false
|
78
|
-
rescue
|
79
|
-
raise "Provided definition could not be read."
|
80
|
-
end
|
81
|
-
|
82
|
-
parse_yaml(definition)
|
83
|
-
end
|
84
|
-
|
85
|
-
def read_yaml_file(file)
|
86
|
-
begin
|
87
|
-
definition = YAML.load_file(file)
|
88
|
-
raise "Not a valid YAML file." if definition.nil? or definition == false
|
89
|
-
rescue
|
90
|
-
raise "File '#{file}' could not be read."
|
66
|
+
# Assuming that the definition is provided as string
|
67
|
+
@appliance_configs << parse_yaml(@appliance_parser.parse_definition(definition, false))
|
91
68
|
end
|
92
|
-
|
93
|
-
parse_yaml(definition)
|
94
69
|
end
|
95
70
|
|
96
|
-
# TODO this needs to be rewritten
|
71
|
+
# TODO this needs to be rewritten - using kwalify it could be possible to instantiate document structure as objects[, or opencascade hash?]
|
97
72
|
def parse_yaml(definition)
|
98
73
|
return definition if definition.is_a?(ApplianceConfig)
|
99
74
|
raise "Provided definition is not a Hash." unless definition.is_a?(Hash)
|
@@ -107,27 +82,15 @@ module BoxGrinder
|
|
107
82
|
|
108
83
|
@log.debug "Adding packages to appliance..."
|
109
84
|
|
110
|
-
unless definition['packages'].nil?
|
111
|
-
if definition['packages'].is_a?(Array)
|
112
|
-
# new format
|
113
|
-
appliance_config.packages = definition['packages']
|
114
|
-
elsif definition['packages'].is_a?(Hash)
|
115
|
-
# legacy format
|
116
|
-
@log.warn "BoxGrinder Build packages section format has been changed. Support for legacy format will be removed in the future. See http://boxgrinder.org/tutorials/appliance-definition/ for more information about current format."
|
117
|
-
appliance_config.packages = definition['packages']['includes'] if definition['packages']['includes'].is_a?(Array)
|
118
|
-
@log.warn "BoxGrinder Build no longer supports package exclusion, the following packages will not be explicitly excluded: #{definition['packages']['excludes'].join(", ")}." if definition['packages']['excludes'].is_a?(Array)
|
119
|
-
else
|
120
|
-
@log.warn "Unsupported format for packages section."
|
121
|
-
end
|
122
|
-
end
|
85
|
+
appliance_config.packages = definition['packages'] unless definition['packages'].nil?
|
123
86
|
|
124
|
-
@log.debug "#{appliance_config.packages.size} package(s) added to appliance."
|
87
|
+
@log.debug "#{appliance_config.packages.size} package(s) added to appliance." if appliance_config.packages
|
125
88
|
|
126
89
|
appliance_config.appliances = definition['appliances'] unless definition['appliances'].nil?
|
127
90
|
appliance_config.repos = definition['repos'] unless definition['repos'].nil?
|
128
91
|
|
129
|
-
appliance_config.version = definition['version']
|
130
|
-
appliance_config.release = definition['release']
|
92
|
+
appliance_config.version = definition['version'] unless definition['version'].nil?
|
93
|
+
appliance_config.release = definition['release'] unless definition['release'].nil?
|
131
94
|
|
132
95
|
unless definition['default_repos'].nil?
|
133
96
|
appliance_config.default_repos = definition['default_repos']
|
@@ -135,9 +98,10 @@ module BoxGrinder
|
|
135
98
|
end
|
136
99
|
|
137
100
|
unless definition['os'].nil?
|
138
|
-
appliance_config.os.name = definition['os']['name']
|
139
|
-
appliance_config.os.version = definition['os']['version']
|
140
|
-
appliance_config.os.password = definition['os']['password']
|
101
|
+
appliance_config.os.name = definition['os']['name'] unless definition['os']['name'].nil?
|
102
|
+
appliance_config.os.version = definition['os']['version'] unless definition['os']['version'].nil?
|
103
|
+
appliance_config.os.password = definition['os']['password'] unless definition['os']['password'].nil?
|
104
|
+
appliance_config.os.pae = definition['os']['pae'] unless definition['os']['pae'].nil?
|
141
105
|
end
|
142
106
|
|
143
107
|
unless definition['hardware'].nil?
|
@@ -157,9 +121,5 @@ module BoxGrinder
|
|
157
121
|
|
158
122
|
appliance_config
|
159
123
|
end
|
160
|
-
|
161
|
-
def read_xml_file(file)
|
162
|
-
raise "Reading XML files is not supported right now. File '#{file}' could not be read."
|
163
|
-
end
|
164
124
|
end
|
165
125
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This is free software; you can redistribute it and/or modify it
|
5
|
+
# under the terms of the GNU Lesser General Public License as
|
6
|
+
# published by the Free Software Foundation; either version 3 of
|
7
|
+
# the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This software is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this software; if not, write to the Free
|
16
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
17
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
18
|
+
|
19
|
+
require 'boxgrinder-core/helpers/log-helper'
|
20
|
+
|
21
|
+
module BoxGrinder
|
22
|
+
class ApplianceTransformationHelper
|
23
|
+
def initialize(latest_schema_version, options = {})
|
24
|
+
@latest_schema_version = latest_schema_version
|
25
|
+
@log = options[:log] || LogHelper.new
|
26
|
+
|
27
|
+
@versions = ['0.9.0']
|
28
|
+
end
|
29
|
+
|
30
|
+
def transform(appliance_definition, version)
|
31
|
+
return appliance_definition if version == @latest_schema_version
|
32
|
+
|
33
|
+
@log.debug "Transforming appliance definition from schema version #{version} to #{@latest_schema_version}..."
|
34
|
+
|
35
|
+
transformations = [version]
|
36
|
+
definition = appliance_definition
|
37
|
+
|
38
|
+
@versions.each do |v|
|
39
|
+
if (transformations.last <=> v) < 0
|
40
|
+
@log.trace "Round #{transformations.size}: transforming from version #{transformations.last} to #{v}..."
|
41
|
+
definition = self.send("to_#{v.gsub(/[-\.]/, '_')}", definition)
|
42
|
+
transformations << v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@log.debug "Following transformation were applied: #{transformations.join(' => ')}." if transformations.size > 1
|
47
|
+
|
48
|
+
definition
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_0_9_0(appliance_definition)
|
52
|
+
packages = appliance_definition['packages']['includes']
|
53
|
+
@log.warn "BoxGrinder no longer supports package exclusion, the following packages will be not be explicitly excluded: #{appliance_definition['packages']['excludes'].join(", ")}." unless appliance_definition['packages']['excludes'].nil?
|
54
|
+
appliance_definition['packages'] = packages
|
55
|
+
appliance_definition
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -18,15 +18,23 @@
|
|
18
18
|
|
19
19
|
require 'logger'
|
20
20
|
require 'rubygems'
|
21
|
-
require 'open4'
|
21
|
+
require 'open4' unless RUBY_PLATFORM =~ /java/
|
22
22
|
|
23
23
|
module BoxGrinder
|
24
|
+
class InterruptionError < Interrupt
|
25
|
+
attr_reader :pid
|
26
|
+
|
27
|
+
def initialize(pid)
|
28
|
+
@pid = pid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
24
32
|
class ExecHelper
|
25
|
-
def initialize(
|
33
|
+
def initialize(options = {})
|
26
34
|
@log = options[:log] || Logger.new(STDOUT)
|
27
35
|
end
|
28
36
|
|
29
|
-
def execute(
|
37
|
+
def execute(command, options = {})
|
30
38
|
redacted = options[:redacted] || []
|
31
39
|
|
32
40
|
redacted_command = command
|
@@ -41,38 +49,57 @@ module BoxGrinder
|
|
41
49
|
STDERR.sync = true
|
42
50
|
|
43
51
|
begin
|
44
|
-
|
45
|
-
|
52
|
+
pid, stdin, stdout, stderr = (RUBY_PLATFORM =~ /java/ ? IO : Open4).send(:popen4, command)
|
53
|
+
threads = []
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
threads << Thread.new(stdout) do |out|
|
56
|
+
out.each do |l|
|
57
|
+
l.chomp!
|
58
|
+
l.strip!
|
51
59
|
|
52
|
-
|
53
|
-
|
54
|
-
end
|
60
|
+
output << "\n#{l}"
|
61
|
+
@log.debug l
|
55
62
|
end
|
63
|
+
end
|
56
64
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
threads << Thread.new(stderr) do |err|
|
66
|
+
err.each do |l|
|
67
|
+
l.chomp!
|
68
|
+
l.strip!
|
61
69
|
|
62
|
-
|
63
|
-
|
64
|
-
end
|
70
|
+
output << "\n#{l}"
|
71
|
+
@log.debug l
|
65
72
|
end
|
66
|
-
threads.each{|t|t.join}
|
67
73
|
end
|
68
74
|
|
69
|
-
|
75
|
+
threads.each { |t| t.join }
|
76
|
+
|
77
|
+
# Assume the process exited cleanly, which can cause some bad behaviour, but I don't see better way
|
78
|
+
# to get reliable status for processes both on MRI and JRuby
|
79
|
+
#
|
80
|
+
# http://jira.codehaus.org/browse/JRUBY-5673
|
81
|
+
status = OpenCascade.new(:exitstatus => 0)
|
82
|
+
|
83
|
+
fakepid, status = Process.waitpid2(pid) if process_alive?(pid)
|
84
|
+
|
85
|
+
raise "process exited with wrong exit status: #{status.exitstatus}" if !(RUBY_PLATFORM =~ /java/) and status.exitstatus != 0
|
70
86
|
|
71
87
|
return output.strip
|
88
|
+
rescue Interrupt
|
89
|
+
raise InterruptionError.new(pid), "Program was interrupted."
|
72
90
|
rescue => e
|
73
91
|
@log.error e.backtrace.join($/)
|
74
92
|
raise "An error occurred while executing command: '#{redacted_command}', #{e.message}"
|
75
93
|
end
|
76
94
|
end
|
95
|
+
|
96
|
+
def process_alive?(pid)
|
97
|
+
begin
|
98
|
+
Process.getpgid(pid)
|
99
|
+
true
|
100
|
+
rescue Errno::ESRCH
|
101
|
+
false
|
102
|
+
end
|
103
|
+
end
|
77
104
|
end
|
78
105
|
end
|