boxgrinder-build 0.3.6 → 0.3.7
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/bin/boxgrinder-build +4 -4
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +26 -2
- data/lib/boxgrinder-build/plugins/delivery/s3/aws-helper.rb +6 -10
- data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +25 -7
- data/lib/boxgrinder-build/plugins/os/base/rpm-based-os-plugin.rb +1 -21
- data/lib/boxgrinder-build/plugins/os/base/validators/rpm-dependency-validator.rb +0 -1
- data/lib/boxgrinder-build/plugins/os/fedora/fedora-plugin.rb +9 -1
- data/lib/boxgrinder-build/plugins/platform/ec2/ec2-plugin.rb +59 -23
- metadata +5 -5
data/bin/boxgrinder-build
CHANGED
@@ -26,7 +26,7 @@ require 'boxgrinder-core/helpers/log-helper'
|
|
26
26
|
require 'boxgrinder-build/helpers/plugin-helper'
|
27
27
|
require 'boxgrinder-build/appliance'
|
28
28
|
|
29
|
-
gem 'boxgrinder-core', '>= 0.0.
|
29
|
+
gem 'boxgrinder-core', '>= 0.0.10'
|
30
30
|
gem 'aws-s3', '>= 0.6.2'
|
31
31
|
gem 'amazon-ec2', '>= 0.9.6'
|
32
32
|
gem 'net-sftp', '>= 2.0.4'
|
@@ -39,8 +39,8 @@ gem 'commander', '>= 4.0.3'
|
|
39
39
|
|
40
40
|
#$stderr.reopen('/dev/null')
|
41
41
|
|
42
|
-
program :name, 'BoxGrinder'
|
43
|
-
program :version, '0.3.
|
42
|
+
program :name, 'BoxGrinder Build'
|
43
|
+
program :version, '0.3.7'
|
44
44
|
program :description, 'A tool for building VM images from simple definition files.'
|
45
45
|
default_command :build
|
46
46
|
|
@@ -75,7 +75,7 @@ module BoxGrinder
|
|
75
75
|
|
76
76
|
appliance_definition_file = args.shift or raise('Appliance definition file is required. Run boxgrinder-build -h for more info')
|
77
77
|
|
78
|
-
raise
|
78
|
+
raise "Appliance definition file '#{appliance_definition_file}' could not be found" unless File.exists?( appliance_definition_file )
|
79
79
|
raise "Not known platform: #{options.platform}. Available platforms: #{PlatformPluginManager.instance.plugins.keys.join(', ')}." if PlatformPluginManager.instance.plugins[options.platform].nil? and options.platform != :none
|
80
80
|
raise "Not known delivery type: #{options.delivery}. Available types: #{DeliveryPluginManager.instance.types.keys.join(', ')}." if DeliveryPluginManager.instance.types.keys.include?(options.delivery).nil? and options.delivery != :none
|
81
81
|
|
@@ -56,8 +56,14 @@ module BoxGrinder
|
|
56
56
|
@log.debug "Launching guestfs..."
|
57
57
|
@guestfs.launch
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
case @guestfs.list_partitions.size
|
60
|
+
when 0
|
61
|
+
mount_partition( @guestfs.list_devices.first, '/' )
|
62
|
+
when 1
|
63
|
+
mount_partition( @guestfs.list_partitions.first, '/' )
|
64
|
+
else
|
65
|
+
mount_partitions
|
66
|
+
end
|
61
67
|
|
62
68
|
@log.debug "Guestfs launched."
|
63
69
|
end
|
@@ -85,5 +91,23 @@ module BoxGrinder
|
|
85
91
|
@guestfs.sh( "rpm --rebuilddb" )
|
86
92
|
@log.debug "Cleaning RPM database finished."
|
87
93
|
end
|
94
|
+
|
95
|
+
def mount_partitions
|
96
|
+
root_partition = nil
|
97
|
+
|
98
|
+
@guestfs.list_partitions.each do |partition|
|
99
|
+
mount_partition( partition, '/' )
|
100
|
+
if @guestfs.exists( '/sbin/e2label' ) != 0
|
101
|
+
root_partition = partition
|
102
|
+
break
|
103
|
+
end
|
104
|
+
@guestfs.umount( partition )
|
105
|
+
end
|
106
|
+
|
107
|
+
@guestfs.list_partitions.each do |partition|
|
108
|
+
next if partition == root_partition
|
109
|
+
mount_partition( partition, @guestfs.sh( "/sbin/e2label #{partition}" ).chomp.strip )
|
110
|
+
end
|
111
|
+
end
|
88
112
|
end
|
89
113
|
end
|
@@ -39,19 +39,15 @@ module BoxGrinder
|
|
39
39
|
attr_reader :ec2
|
40
40
|
attr_reader :s3
|
41
41
|
|
42
|
-
def bucket_key( appliance_name )
|
43
|
-
"#{@plugin_config['bucket']}/#{appliance_name}/#{@appliance_config.version}.#{@appliance_config.release}/#{@appliance_config.hardware.arch}"
|
42
|
+
def bucket_key( appliance_name, path )
|
43
|
+
"#{@plugin_config['bucket']}#{path}/#{appliance_name}/#{@appliance_config.version}.#{@appliance_config.release}/#{@appliance_config.hardware.arch}"
|
44
44
|
end
|
45
45
|
|
46
|
-
def bucket_manifest_key( appliance_name )
|
47
|
-
"#{bucket_key( appliance_name )}/#{appliance_name}.ec2.manifest.xml"
|
46
|
+
def bucket_manifest_key( appliance_name, path )
|
47
|
+
"#{bucket_key( appliance_name, path )}/#{appliance_name}.ec2.manifest.xml"
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
!ami_info( appliance_name ).nil?
|
52
|
-
end
|
53
|
-
|
54
|
-
def ami_info( appliance_name )
|
50
|
+
def ami_info( appliance_name, path )
|
55
51
|
ami_info = nil
|
56
52
|
|
57
53
|
images = @ec2.describe_images( :owner_id => @plugin_config['account_number'] ).imagesSet
|
@@ -59,7 +55,7 @@ module BoxGrinder
|
|
59
55
|
return nil if images.nil?
|
60
56
|
|
61
57
|
for image in images.item do
|
62
|
-
ami_info = image if (image.imageLocation.eql?( bucket_manifest_key( appliance_name ) ))
|
58
|
+
ami_info = image if (image.imageLocation.eql?( bucket_manifest_key( appliance_name, path ) ))
|
63
59
|
end
|
64
60
|
|
65
61
|
ami_info
|
@@ -28,7 +28,9 @@ module BoxGrinder
|
|
28
28
|
class S3Plugin < BaseDeliveryPlugin
|
29
29
|
|
30
30
|
AMI_OSES = {
|
31
|
-
'fedora'
|
31
|
+
'fedora' => [ '11' ],
|
32
|
+
'centos' => [ '5' ],
|
33
|
+
'rhel' => [ '5' ]
|
32
34
|
}
|
33
35
|
|
34
36
|
KERNELS = {
|
@@ -38,6 +40,23 @@ module BoxGrinder
|
|
38
40
|
'i386' => { :aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc' },
|
39
41
|
'x86_64' => { :aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da' }
|
40
42
|
}
|
43
|
+
},
|
44
|
+
'centos' => {
|
45
|
+
'5' => {
|
46
|
+
'i386' => { :aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc' },
|
47
|
+
'x86_64' => { :aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da' }
|
48
|
+
}
|
49
|
+
},
|
50
|
+
'rhel' => {
|
51
|
+
'5' => {
|
52
|
+
'i386' => { :aki => 'aki-a71cf9ce', :ari => 'ari-a51cf9cc' },
|
53
|
+
'x86_64' => { :aki => 'aki-b51cf9dc', :ari => 'ari-b31cf9da' }
|
54
|
+
}
|
55
|
+
# '5' => {
|
56
|
+
# 'i386' => { :aki => 'aki-e3a54b8a', :ari => 'ari-f9a54b90' },
|
57
|
+
# 'x86_64' => { :aki => 'aki-ffa54b96', :ari => 'ari-fda54b94' }
|
58
|
+
# }
|
59
|
+
|
41
60
|
}
|
42
61
|
}
|
43
62
|
}
|
@@ -135,12 +154,12 @@ module BoxGrinder
|
|
135
154
|
|
136
155
|
def image_already_uploaded?
|
137
156
|
begin
|
138
|
-
bucket = Bucket.find(@
|
157
|
+
bucket = Bucket.find(@plugin_config['bucket'])
|
139
158
|
rescue
|
140
159
|
return false
|
141
160
|
end
|
142
161
|
|
143
|
-
manifest_location = @aws_helper.bucket_manifest_key(@appliance_config.name)
|
162
|
+
manifest_location = @aws_helper.bucket_manifest_key(@appliance_config.name, @plugin_config['path'])
|
144
163
|
manifest_location = manifest_location[manifest_location.index("/") + 1, manifest_location.length]
|
145
164
|
|
146
165
|
for object in bucket.objects do
|
@@ -153,20 +172,19 @@ module BoxGrinder
|
|
153
172
|
def upload_image
|
154
173
|
@log.info "Uploading #{@appliance_config.name} AMI to bucket '#{@plugin_config['bucket']}'..."
|
155
174
|
|
156
|
-
@exec_helper.execute("ec2-upload-bundle -b #{@aws_helper.bucket_key(@appliance_config.name)} -m #{@ami_manifest} -a #{@plugin_config['access_key']} -s #{@plugin_config['secret_access_key']} --retry")
|
175
|
+
@exec_helper.execute("ec2-upload-bundle -b #{@aws_helper.bucket_key(@appliance_config.name, @plugin_config['path'])} -m #{@ami_manifest} -a #{@plugin_config['access_key']} -s #{@plugin_config['secret_access_key']} --retry")
|
157
176
|
end
|
158
177
|
|
159
178
|
def register_image
|
160
|
-
ami_info = @aws_helper.ami_info(@appliance_config.name)
|
179
|
+
ami_info = @aws_helper.ami_info(@appliance_config.name, @plugin_config['path'])
|
161
180
|
|
162
181
|
if ami_info
|
163
182
|
@log.info "Image is registered under id: #{ami_info.imageId}"
|
164
183
|
return
|
165
184
|
else
|
166
|
-
ami_info = @aws_helper.ec2.register_image(:image_location => @aws_helper.bucket_manifest_key(@appliance_config.name))
|
185
|
+
ami_info = @aws_helper.ec2.register_image(:image_location => @aws_helper.bucket_manifest_key(@appliance_config.name, @plugin_config['path']))
|
167
186
|
@log.info "Image successfully registered under id: #{ami_info.imageId}."
|
168
187
|
end
|
169
188
|
end
|
170
|
-
|
171
189
|
end
|
172
190
|
end
|
@@ -49,8 +49,6 @@ module BoxGrinder
|
|
49
49
|
customize( @deliverables[:disk] ) do |guestfs, guestfs_helper|
|
50
50
|
@log.info "Executing post operations after build..."
|
51
51
|
|
52
|
-
mount_partitions( guestfs, guestfs_helper ) if guestfs.list_partitions.size > 1
|
53
|
-
|
54
52
|
if @appliance_config.post.base.size > 0
|
55
53
|
@appliance_config.post.base.each do |cmd|
|
56
54
|
@log.debug "Executing #{cmd}"
|
@@ -74,24 +72,6 @@ module BoxGrinder
|
|
74
72
|
@log.info "Base image for #{@appliance_config.name} appliance was built successfully."
|
75
73
|
end
|
76
74
|
|
77
|
-
def mount_partitions( guestfs, guestfs_helper )
|
78
|
-
root_partition = nil
|
79
|
-
|
80
|
-
guestfs.list_partitions.each do |partition|
|
81
|
-
guestfs_helper.mount_partition( partition, '/' )
|
82
|
-
if guestfs.exists( '/sbin/e2label' ) != 0
|
83
|
-
root_partition = partition
|
84
|
-
break
|
85
|
-
end
|
86
|
-
guestfs.umount( partition )
|
87
|
-
end
|
88
|
-
|
89
|
-
guestfs.list_partitions.each do |partition|
|
90
|
-
next if partition == root_partition
|
91
|
-
guestfs_helper.mount_partition( partition, guestfs.sh( "/sbin/e2label #{partition}" ).chomp.strip )
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
75
|
def change_configuration( guestfs )
|
96
76
|
@log.debug "Changing configuration files using augeas..."
|
97
77
|
guestfs.aug_init( "/", 0 )
|
@@ -125,7 +105,7 @@ module BoxGrinder
|
|
125
105
|
@log.debug "Installing repositories from appliance definition file..."
|
126
106
|
@appliance_config.repos.each do |repo|
|
127
107
|
if repo['ephemeral']
|
128
|
-
@log.debug "Repository '#{repo['name']}' is
|
108
|
+
@log.debug "Repository '#{repo['name']}' is an ephemeral repo. It'll not be installed in the appliance."
|
129
109
|
next
|
130
110
|
end
|
131
111
|
|
@@ -72,7 +72,6 @@ module BoxGrinder
|
|
72
72
|
if invalid_names.size == 0
|
73
73
|
@log.info "All additional packages for #{@appliance_config.simple_name} appliance successfully resolved."
|
74
74
|
else
|
75
|
-
puts invalid_names.to_yaml
|
76
75
|
raise "Package#{invalid_names.size > 1 ? "s" : ""} #{invalid_names.join(', ')} for #{@appliance_config.simple_name} appliance not found in repositories. Please check package names in appliance definition file."
|
77
76
|
end
|
78
77
|
end
|
@@ -26,6 +26,14 @@ module BoxGrinder
|
|
26
26
|
class FedoraPlugin < RPMBasedOSPlugin
|
27
27
|
|
28
28
|
FEDORA_REPOS = {
|
29
|
+
"13" => {
|
30
|
+
"base" => {
|
31
|
+
"mirrorlist" => "http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-13&arch=#ARCH#"
|
32
|
+
},
|
33
|
+
"updates" => {
|
34
|
+
"mirrorlist" => "http://mirrors.fedoraproject.org/mirrorlist?repo=updates-released-f13&arch=#ARCH#"
|
35
|
+
}
|
36
|
+
},
|
29
37
|
"12" => {
|
30
38
|
"base" => {
|
31
39
|
"mirrorlist" => "http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-12&arch=#ARCH#"
|
@@ -55,7 +63,7 @@ module BoxGrinder
|
|
55
63
|
:name => :fedora,
|
56
64
|
:full_name => "Fedora",
|
57
65
|
:type => :linux,
|
58
|
-
:versions => ["11", "12", "rawhide"]
|
66
|
+
:versions => ["11", "12", "13", "rawhide"]
|
59
67
|
}
|
60
68
|
end
|
61
69
|
|
@@ -30,7 +30,9 @@ module BoxGrinder
|
|
30
30
|
end
|
31
31
|
|
32
32
|
SUPPORTED_OSES = {
|
33
|
-
'
|
33
|
+
'rhel' => [ '5' ],
|
34
|
+
'centos' => [ '5' ],
|
35
|
+
'fedora' => [ '11' ]
|
34
36
|
}
|
35
37
|
|
36
38
|
REGIONS = {'us_east' => 'url'}
|
@@ -41,8 +43,19 @@ module BoxGrinder
|
|
41
43
|
'i386' => { :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.i686.rpm' },
|
42
44
|
'x86_64' => { :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.x86_64.rpm' }
|
43
45
|
}
|
46
|
+
},
|
47
|
+
'centos' => {
|
48
|
+
'5' => {
|
49
|
+
'i386' => { :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.i686.rpm' },
|
50
|
+
'x86_64' => { :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.x86_64.rpm' }
|
51
|
+
}
|
52
|
+
},
|
53
|
+
'rhel' => {
|
54
|
+
'5' => {
|
55
|
+
'i386' => { :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.i686.rpm' },
|
56
|
+
'x86_64' => { :rpm => 'http://repo.oddthesis.org/packages/other/kernel-xen-2.6.21.7-2.fc8.x86_64.rpm' }
|
57
|
+
}
|
44
58
|
}
|
45
|
-
|
46
59
|
}
|
47
60
|
|
48
61
|
def after_init
|
@@ -65,7 +78,7 @@ module BoxGrinder
|
|
65
78
|
return
|
66
79
|
end
|
67
80
|
|
68
|
-
unless SUPPORTED_OSES[@appliance_config.os.name].include?(@appliance_config.os.version)
|
81
|
+
unless !SUPPORTED_OSES[@appliance_config.os.name].nil? and SUPPORTED_OSES[@appliance_config.os.name].include?(@appliance_config.os.version)
|
69
82
|
@log.error "EC2 platform plugin for Linux operating systems supports: #{supported_os}. Your OS is #{@appliance_config.os.name} #{@appliance_config.os.version}."
|
70
83
|
return
|
71
84
|
end
|
@@ -81,23 +94,22 @@ module BoxGrinder
|
|
81
94
|
raise "Error while preparing EC2 disk image. See logs for more info"
|
82
95
|
end
|
83
96
|
|
84
|
-
raw_disk_offset = calculate_disk_offset(raw_disk)
|
85
|
-
|
86
97
|
ec2_disk_mount_dir = "#{@appliance_config.path.dir.build}/tmp/ec2-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
|
87
98
|
raw_disk_mount_dir = "#{@appliance_config.path.dir.build}/tmp/raw-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
|
88
99
|
|
89
100
|
|
90
101
|
begin
|
91
|
-
|
92
|
-
|
102
|
+
ec2_mounts = mount_image( @deliverables[:disk], ec2_disk_mount_dir )
|
103
|
+
raw_mounts = mount_image( raw_disk, raw_disk_mount_dir )
|
93
104
|
rescue => e
|
105
|
+
@log.debug e
|
94
106
|
raise "Error while mounting image. See logs for more info"
|
95
107
|
end
|
96
108
|
|
97
109
|
sync_files(raw_disk_mount_dir, ec2_disk_mount_dir)
|
98
110
|
|
99
|
-
umount_image(raw_disk, raw_disk_mount_dir,
|
100
|
-
umount_image(@deliverables[:disk], ec2_disk_mount_dir,
|
111
|
+
umount_image(raw_disk, raw_disk_mount_dir, raw_mounts)
|
112
|
+
umount_image(@deliverables[:disk], ec2_disk_mount_dir, ec2_mounts)
|
101
113
|
|
102
114
|
customize(@deliverables[:disk]) do |guestfs, guestfs_helper|
|
103
115
|
create_devices(guestfs)
|
@@ -154,30 +166,51 @@ module BoxGrinder
|
|
154
166
|
@log.debug "Filesystem created"
|
155
167
|
end
|
156
168
|
|
157
|
-
def
|
169
|
+
def calculate_disk_offsets( disk )
|
170
|
+
@log.debug "Calculating offsets for '#{File.basename(disk)}' disk..."
|
158
171
|
loop_device = get_loop_device
|
159
172
|
|
160
173
|
@exec_helper.execute("sudo losetup #{loop_device} #{disk}")
|
161
|
-
|
174
|
+
offsets = @exec_helper.execute("sudo parted #{loop_device} 'unit B print' | grep -e '^ [0-9]' | awk '{ print $2 }'").scan(/\d+/)
|
162
175
|
@exec_helper.execute("sudo losetup -d #{loop_device}")
|
163
176
|
|
164
|
-
|
177
|
+
@log.trace "Offsets:\n#{offsets}"
|
178
|
+
|
179
|
+
offsets
|
165
180
|
end
|
166
181
|
|
167
|
-
def mount_image(disk, mount_dir
|
168
|
-
|
182
|
+
def mount_image(disk, mount_dir)
|
183
|
+
offsets = calculate_disk_offsets( disk )
|
169
184
|
|
170
|
-
@log.debug "Mounting image #{File.basename(disk)} in #{mount_dir}
|
185
|
+
@log.debug "Mounting image #{File.basename(disk)} in #{mount_dir}..."
|
171
186
|
FileUtils.mkdir_p(mount_dir)
|
172
|
-
@exec_helper.execute("sudo losetup -o #{offset.to_s} #{loop_device} #{disk}")
|
173
|
-
@exec_helper.execute("sudo mount #{loop_device} -t ext3 #{ mount_dir}")
|
174
187
|
|
175
|
-
|
188
|
+
mounts = {}
|
189
|
+
|
190
|
+
offsets.each do |offset|
|
191
|
+
loop_device = get_loop_device
|
192
|
+
@exec_helper.execute("sudo losetup -o #{offset.to_s} #{loop_device} #{disk}")
|
193
|
+
label = @exec_helper.execute("e2label #{loop_device}").strip.chomp
|
194
|
+
label = '/' if label == ''
|
195
|
+
mounts[label] = loop_device
|
196
|
+
end
|
197
|
+
|
198
|
+
@exec_helper.execute("sudo mount #{mounts['/']} -t ext3 #{mount_dir}")
|
199
|
+
|
200
|
+
mounts.each { |mount_point, loop_device| @exec_helper.execute("sudo mount #{loop_device} -t ext3 #{mount_dir}/#{mount_point}") unless mount_point == '/' }
|
201
|
+
|
202
|
+
@log.trace "Mounts:\n#{mounts}"
|
203
|
+
|
204
|
+
mounts
|
176
205
|
end
|
177
206
|
|
178
|
-
def umount_image(disk, mount_dir,
|
179
|
-
@log.debug "Unmounting image #{File.basename(disk)}"
|
180
|
-
|
207
|
+
def umount_image(disk, mount_dir, mounts)
|
208
|
+
@log.debug "Unmounting image '#{File.basename(disk)}'..."
|
209
|
+
|
210
|
+
mounts.each { |mount_point, loop_device| @exec_helper.execute("sudo umount -d #{loop_device}") unless mount_point == '/' }
|
211
|
+
|
212
|
+
@exec_helper.execute("sudo umount -d #{mounts['/']}")
|
213
|
+
|
181
214
|
FileUtils.rm_rf(mount_dir)
|
182
215
|
end
|
183
216
|
|
@@ -239,8 +272,11 @@ module BoxGrinder
|
|
239
272
|
"ec2-ami-tools.noarch.rpm" => "http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm"
|
240
273
|
}
|
241
274
|
|
242
|
-
|
243
|
-
|
275
|
+
begin
|
276
|
+
kernel_rpm = KERNELS[@appliance_config.os.name][@appliance_config.os.version][@appliance_config.hardware.arch][:rpm]
|
277
|
+
rpms[File.basename(kernel_rpm)] = kernel_rpm
|
278
|
+
rescue
|
279
|
+
end
|
244
280
|
|
245
281
|
cache_rpms(rpms)
|
246
282
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 7
|
9
|
+
version: 0.3.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- BoxGrinder Project
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-30 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -27,8 +27,8 @@ dependencies:
|
|
27
27
|
segments:
|
28
28
|
- 0
|
29
29
|
- 0
|
30
|
-
-
|
31
|
-
version: 0.0.
|
30
|
+
- 10
|
31
|
+
version: 0.0.10
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|