boxgrinder-build 0.10.0 → 0.10.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 +11 -0
- data/Manifest +6 -7
- data/Rakefile +11 -6
- data/bash_completion +37 -0
- data/bin/boxgrinder-build +20 -5
- data/boxgrinder-build.gemspec +4 -4
- data/lib/boxgrinder-build.rb +2 -1
- data/lib/boxgrinder-build/appliance.rb +26 -24
- data/lib/boxgrinder-build/helpers/augeas-helper.rb +1 -1
- data/lib/boxgrinder-build/helpers/ec2-helper.rb +2 -2
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +1 -1
- data/lib/boxgrinder-build/helpers/s3-helper.rb +2 -2
- data/lib/boxgrinder-build/managers/plugin-manager.rb +1 -1
- data/lib/boxgrinder-build/plugins/delivery/ebs/ebs-plugin.rb +1 -1
- data/lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb +2 -2
- data/lib/boxgrinder-build/plugins/delivery/openstack/openstack-plugin.rb +3 -3
- data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +16 -10
- data/lib/boxgrinder-build/plugins/os/centos/centos-plugin.rb +1 -1
- data/lib/boxgrinder-build/plugins/os/fedora/fedora-plugin.rb +1 -1
- data/lib/boxgrinder-build/plugins/os/rhel/rhel-plugin.rb +1 -1
- data/lib/boxgrinder-build/plugins/os/rpm-based/kickstart.rb +5 -1
- data/lib/boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin.rb +8 -3
- data/lib/boxgrinder-build/plugins/os/rpm-based/rpm-dependency-validator.rb +1 -1
- data/lib/boxgrinder-build/plugins/os/sl/sl-plugin.rb +1 -1
- data/lib/boxgrinder-build/plugins/platform/ec2/ec2-plugin.rb +1 -1
- data/lib/boxgrinder-build/util/concurrent/get_set.rb +46 -0
- data/lib/boxgrinder-build/util/permissions/fs-monitor.rb +182 -0
- data/lib/boxgrinder-build/util/permissions/fs-observer.rb +82 -0
- data/lib/boxgrinder-build/util/permissions/user-switcher.rb +42 -0
- data/rubygem-boxgrinder-build.spec +25 -3
- data/spec/appliance-spec.rb +69 -82
- data/spec/helpers/augeas-helper-spec.rb +0 -2
- data/spec/helpers/guestfs-helper-spec.rb +1 -3
- data/spec/helpers/image-helper-spec.rb +0 -2
- data/spec/helpers/linux-helper-spec.rb +0 -2
- data/spec/helpers/package-helper-spec.rb +0 -2
- data/spec/helpers/plugin-helper-spec.rb +0 -2
- data/spec/helpers/s3-helper-spec.rb +0 -2
- data/spec/managers/plugin-manager-spec.rb +0 -2
- data/spec/plugins/base-plugin-spec.rb +0 -2
- data/spec/plugins/delivery/ebs/ebs-plugin-spec.rb +0 -2
- data/spec/plugins/delivery/elastichosts/elastichosts-plugin-spec.rb +3 -5
- data/spec/plugins/delivery/libvirt/libvirt-plugin-spec.rb +19 -17
- data/spec/plugins/delivery/local/local-plugin-spec.rb +0 -2
- data/spec/plugins/delivery/s3/s3-plugin-spec.rb +6 -8
- data/spec/plugins/delivery/sftp/sftp-plugin-spec.rb +0 -2
- data/spec/plugins/os/centos/centos-plugin-spec.rb +0 -2
- data/spec/plugins/os/fedora/fedora-plugin-spec.rb +0 -2
- data/spec/plugins/os/rhel/rhel-plugin-spec.rb +0 -2
- data/spec/plugins/os/rpm-based/kickstart-spec.rb +0 -2
- data/spec/plugins/os/rpm-based/rpm-based-os-plugin-spec.rb +16 -4
- data/spec/plugins/os/rpm-based/rpm-dependency-validator-spec.rb +0 -2
- data/spec/plugins/platform/ec2/ec2-plugin-spec.rb +0 -2
- data/spec/plugins/platform/virtualbox/virtualbox-plugin-spec.rb +1 -3
- data/spec/plugins/platform/virtualpc/virtualpc-plugin-spec.rb +0 -1
- data/spec/plugins/platform/vmware/vmware-plugin-spec.rb +25 -24
- data/spec/rcov_helper.rb +2 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/util/concurrent/get-set-spec.rb +43 -0
- data/spec/util/permissions/fs-monitor-spec.rb +233 -0
- data/spec/util/permissions/fs-observer-spec.rb +141 -0
- data/spec/util/permissions/user-switcher-spec.rb +69 -0
- metadata +20 -5
@@ -20,7 +20,7 @@ require 'boxgrinder-build/plugins/os/rhel/rhel-plugin'
|
|
20
20
|
|
21
21
|
module BoxGrinder
|
22
22
|
class CentOSPlugin < RHELPlugin
|
23
|
-
plugin :type => :os, :name => :centos, :full_name => "CentOS", :versions => ["5", "6"]
|
23
|
+
plugin :type => :os, :name => :centos, :full_name => "CentOS", :versions => ["5", "6"], :require_root => true
|
24
24
|
|
25
25
|
def after_init
|
26
26
|
super
|
@@ -20,7 +20,7 @@ require 'boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin'
|
|
20
20
|
|
21
21
|
module BoxGrinder
|
22
22
|
class FedoraPlugin < RPMBasedOSPlugin
|
23
|
-
plugin :type => :os, :name => :fedora, :full_name => "Fedora", :versions => ["13", "14", "15", "16", "rawhide"]
|
23
|
+
plugin :type => :os, :name => :fedora, :full_name => "Fedora", :versions => ["13", "14", "15", "16", "rawhide"], :require_root => true
|
24
24
|
|
25
25
|
def after_init
|
26
26
|
super
|
@@ -20,7 +20,7 @@ require 'boxgrinder-build/plugins/os/rpm-based/rpm-based-os-plugin'
|
|
20
20
|
|
21
21
|
module BoxGrinder
|
22
22
|
class RHELPlugin < RPMBasedOSPlugin
|
23
|
-
plugin :type => :os, :name => :rhel, :full_name => "Red Hat Enterprise Linux", :versions => ['5', '6']
|
23
|
+
plugin :type => :os, :name => :rhel, :full_name => "Red Hat Enterprise Linux", :versions => ['5', '6'], :require_root => true
|
24
24
|
|
25
25
|
def after_init
|
26
26
|
super
|
@@ -37,7 +37,7 @@ module BoxGrinder
|
|
37
37
|
|
38
38
|
def create
|
39
39
|
template = "#{File.dirname(__FILE__)}/src/appliance.ks.erb"
|
40
|
-
kickstart = ERB.new(File.read(template)).result(build_definition.
|
40
|
+
kickstart = ERB.new(File.read(template)).result(build_definition.get_binding)
|
41
41
|
File.open(@kickstart_file, 'w') { |f| f.write(kickstart) }
|
42
42
|
|
43
43
|
@kickstart_file
|
@@ -54,6 +54,10 @@ module BoxGrinder
|
|
54
54
|
self[sym.to_s]
|
55
55
|
end
|
56
56
|
|
57
|
+
def definition.get_binding
|
58
|
+
binding
|
59
|
+
end
|
60
|
+
|
57
61
|
cost = 40
|
58
62
|
|
59
63
|
definition['mount_points'] = @linux_helper.partition_mount_points(@appliance_config.hardware.partitions)
|
@@ -147,7 +147,7 @@ module BoxGrinder
|
|
147
147
|
@log.debug "Cleaning appliance-creator mount points..."
|
148
148
|
|
149
149
|
Dir["#{@dir.tmp}/imgcreate-*"].each do |dir|
|
150
|
-
dev_mapper = @exec_helper.execute
|
150
|
+
dev_mapper = @exec_helper.execute("mount | grep #{dir} | awk '{print $1}'").split("\n")
|
151
151
|
|
152
152
|
mappings = {}
|
153
153
|
|
@@ -158,7 +158,7 @@ module BoxGrinder
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
-
(['/var/cache/yum', '/dev/shm', '/dev/pts', '/proc', '/sys'] + @appliance_config.hardware.partitions.keys.reverse).each do |mount_point|
|
161
|
+
(['/var/cache/yum', '/dev/shm', '/dev/pts', '/proc', '/sys'] + @appliance_config.hardware.partitions.keys.sort.reverse).each do |mount_point|
|
162
162
|
@log.trace "Unmounting '#{mount_point}'..."
|
163
163
|
@exec_helper.execute "umount -d #{dir}/install_root#{mount_point}"
|
164
164
|
end
|
@@ -251,6 +251,11 @@ module BoxGrinder
|
|
251
251
|
|
252
252
|
def install_repos(guestfs)
|
253
253
|
@log.debug "Installing repositories from appliance definition file..."
|
254
|
+
|
255
|
+
# It seems that the directory is not always created by default if default repos are inhibited (e.g. SL6)
|
256
|
+
yum_d = '/etc/yum.repos.d/'
|
257
|
+
guestfs.mkdir_p(yum_d) if guestfs.exists(yum_d) == 0
|
258
|
+
|
254
259
|
@appliance_config.repos.each do |repo|
|
255
260
|
if repo['ephemeral']
|
256
261
|
@log.debug "Repository '#{repo['name']}' is an ephemeral repo. It'll not be installed in the appliance."
|
@@ -264,7 +269,7 @@ module BoxGrinder
|
|
264
269
|
repo_file << ("#{type}=#{repo[type]}\n") unless repo[type].nil?
|
265
270
|
end
|
266
271
|
|
267
|
-
guestfs.write_file("
|
272
|
+
guestfs.write_file("#{yum_d}#{repo['name']}.repo", repo_file, 0)
|
268
273
|
end
|
269
274
|
@log.debug "Repositories installed."
|
270
275
|
end
|
@@ -20,7 +20,7 @@ require 'boxgrinder-build/plugins/os/rhel/rhel-plugin'
|
|
20
20
|
|
21
21
|
module BoxGrinder
|
22
22
|
class ScientificLinuxPlugin < RHELPlugin
|
23
|
-
plugin :type => :os, :name => :sl, :full_name => "Scientific Linux", :versions => ["5", "6"]
|
23
|
+
plugin :type => :os, :name => :sl, :full_name => "Scientific Linux", :versions => ["5", "6"], :require_root => true
|
24
24
|
|
25
25
|
SL_REPOS = {
|
26
26
|
"5" => {
|
@@ -22,7 +22,7 @@ require 'tempfile'
|
|
22
22
|
|
23
23
|
module BoxGrinder
|
24
24
|
class EC2Plugin < BasePlugin
|
25
|
-
plugin :type => :platform, :name => :ec2, :full_name => "Amazon Elastic Compute Cloud (Amazon EC2)"
|
25
|
+
plugin :type => :platform, :name => :ec2, :full_name => "Amazon Elastic Compute Cloud (Amazon EC2)", :require_root => true
|
26
26
|
|
27
27
|
def after_init
|
28
28
|
register_deliverable(:disk => "#{@appliance_config.name}.ec2")
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2012 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 'thread'
|
20
|
+
|
21
|
+
class GetSet
|
22
|
+
def initialize(initial_state=false)
|
23
|
+
@val = initial_state
|
24
|
+
@mutex = Mutex.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Atomic get-and-set.
|
28
|
+
#
|
29
|
+
# When used with a block, the existing value is provided as
|
30
|
+
# an argument to the block. The block's return value sets the
|
31
|
+
# object's value state.
|
32
|
+
#
|
33
|
+
# When used without a block; if a nil +set_val+ parameter is
|
34
|
+
# provided the existing state is returned. Else the object
|
35
|
+
# value state is set to +set_val+
|
36
|
+
def get_set(set_val=nil, &blk)
|
37
|
+
@mutex.synchronize do
|
38
|
+
if block_given?
|
39
|
+
@val = blk.call(@val)
|
40
|
+
else
|
41
|
+
@val = set_val unless set_val.nil?
|
42
|
+
end
|
43
|
+
@val
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2012 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 'thread'
|
20
|
+
require 'observer'
|
21
|
+
require 'pathname'
|
22
|
+
require 'singleton'
|
23
|
+
|
24
|
+
require 'boxgrinder-build/util/concurrent/get_set'
|
25
|
+
|
26
|
+
module BoxGrinder
|
27
|
+
class FSMonitor
|
28
|
+
include Singleton
|
29
|
+
include Observable
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@flag = GetSet.new
|
33
|
+
@lock_a = Mutex.new
|
34
|
+
@lock_b = Mutex.new
|
35
|
+
set_hooks
|
36
|
+
end
|
37
|
+
|
38
|
+
# Start capturing paths. Providing a block automatically stops the
|
39
|
+
# capture process upon termination of the scope.
|
40
|
+
#
|
41
|
+
# @param Array<#update> Observers to be notified of capture
|
42
|
+
# events. Each observer should expect a hash{} containing a
|
43
|
+
# +:command+, and potentially +:data+.
|
44
|
+
#
|
45
|
+
# @yield Block that automatically calls #stop at the end of scope
|
46
|
+
# to cease capture.
|
47
|
+
def capture(*observers, &block)
|
48
|
+
@lock_a.synchronize do
|
49
|
+
add_observers(observers)
|
50
|
+
_capture(&block)
|
51
|
+
|
52
|
+
if block_given?
|
53
|
+
yield
|
54
|
+
_stop
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Explicitly stop capturing paths. This should be utilised if
|
60
|
+
# capture was not used with a block. Fires the +:stop_capture+
|
61
|
+
# command to indicate that capturing has ceased.
|
62
|
+
def stop
|
63
|
+
@lock_a.synchronize { _stop }
|
64
|
+
end
|
65
|
+
|
66
|
+
# Stop any capturing and delete all observers. Useful for testing.
|
67
|
+
# @see #stop
|
68
|
+
def reset
|
69
|
+
@lock_a.synchronize do
|
70
|
+
_stop
|
71
|
+
delete_observers
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Add a path string. Called by the hooked methods when an
|
76
|
+
# applicable action is triggered and capturing is enabled. Fires
|
77
|
+
# the +:add_path+ command, and includes the full path as +:data+.
|
78
|
+
#
|
79
|
+
# If no observers have been assigned before a path is added, they
|
80
|
+
# will be silently lost.
|
81
|
+
#
|
82
|
+
# @param [String] path Filesystem path.
|
83
|
+
# @return [Boolean] False if no observers were present.
|
84
|
+
def add_path(path)
|
85
|
+
@lock_b.synchronize do
|
86
|
+
changed(true)
|
87
|
+
notify_observers(:command => :add_path, :data => realpath(path))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Trigger ownership change immediately, but without ceasing. Fires
|
92
|
+
# the +:chown+ command on all observers.
|
93
|
+
#
|
94
|
+
# @return [boolean] False if no observers were present.
|
95
|
+
def trigger
|
96
|
+
changed(true)
|
97
|
+
notify_observers(:command => :chown)
|
98
|
+
end
|
99
|
+
|
100
|
+
private # Not threadsafe
|
101
|
+
|
102
|
+
# The hooks will all use the same get-and-set to determine when to
|
103
|
+
# begin/cease capturing paths.
|
104
|
+
def _capture
|
105
|
+
@flag.get_set(true)
|
106
|
+
end
|
107
|
+
|
108
|
+
def _stop
|
109
|
+
@flag.get_set(false)
|
110
|
+
changed(true)
|
111
|
+
notify_observers(:command => :stop_capture)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Hooks to capture any standard file, link or directory creation. Other
|
115
|
+
# methods (e.g. FileUtils#mkdir_p, FileUtils#move), ultimately bottom out
|
116
|
+
# into these primitive functions.
|
117
|
+
def set_hooks
|
118
|
+
# Final splat var captures any other variables we are not interested in,
|
119
|
+
# and avoids them being squashed into the final var.
|
120
|
+
eigen_capture(File, [:open, :new], @flag) do |klazz, path, mode, *other|
|
121
|
+
add_path(path) if klazz == File && mode =~ /^(t|b)?((w|a)[+]?)(t|b)?$/
|
122
|
+
end
|
123
|
+
|
124
|
+
eigen_capture(File, [:rename, :symlink, :link], @flag) do |klazz, old, new, *other|
|
125
|
+
add_path(new)
|
126
|
+
end
|
127
|
+
|
128
|
+
eigen_capture(Dir, :mkdir, @flag) do |klazz, path, *other|
|
129
|
+
add_path(root_dir(path))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Hooks into class methods by accessing the eigenclass (virtual class).
|
134
|
+
def eigen_capture(klazz, m_sym, flag, &blk)
|
135
|
+
v_klazz = (class << klazz; self; end)
|
136
|
+
instance_capture(v_klazz, m_sym, flag, &blk)
|
137
|
+
end
|
138
|
+
|
139
|
+
def instance_capture(klazz, m_sym, flag, &blk)
|
140
|
+
Array(m_sym).each{ |sym| alias_and_capture(klazz, sym, flag, &blk) }
|
141
|
+
end
|
142
|
+
|
143
|
+
# Cracks open the target class, and injects a wrapper to enable
|
144
|
+
# monitoring. By aliasing the original method the wrapper intercepts the
|
145
|
+
# call, which it forwards onto the 'real' method before executing the hook.
|
146
|
+
#
|
147
|
+
# The hook's functionality is provided via a &block, which is passed the
|
148
|
+
# caller's +self+ in addition to the wrapped method's parameters.
|
149
|
+
#
|
150
|
+
# Locking the +flag+ signals the hook to begin capturing.
|
151
|
+
def alias_and_capture(klazz, m_sym, flag, &blk)
|
152
|
+
alias_m_sym = "__alias_#{m_sym}"
|
153
|
+
|
154
|
+
klazz.class_eval do
|
155
|
+
alias_method alias_m_sym, m_sym
|
156
|
+
|
157
|
+
define_method(m_sym) do |*args, &blx|
|
158
|
+
response = send(alias_m_sym, *args, &blx)
|
159
|
+
blk.call(self, *args) if flag.get_set
|
160
|
+
response
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_observers(observers)
|
166
|
+
observers.each{ |o| add_observer(o) unless o.nil? }
|
167
|
+
end
|
168
|
+
|
169
|
+
# Transform relative to absolute path
|
170
|
+
def realpath(path)
|
171
|
+
Pathname.new(path).realpath.to_s
|
172
|
+
end
|
173
|
+
|
174
|
+
# For a path relative such as 'x/y/z' returns 'x'. Useful for #mkdir_p
|
175
|
+
# where the entire new path is returned at once.
|
176
|
+
def root_dir(relpath)
|
177
|
+
r = relpath.match(%r(^[/]?.+?[/$]))
|
178
|
+
return relpath if r.nil?
|
179
|
+
r[0] || relpath
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2012 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 'fileutils'
|
20
|
+
require 'set'
|
21
|
+
|
22
|
+
module BoxGrinder
|
23
|
+
class FSObserver
|
24
|
+
attr_accessor :path_set
|
25
|
+
attr_accessor :filter_set
|
26
|
+
|
27
|
+
# @param [Integer] user The uid to switch from root to
|
28
|
+
# @param [Integer] group The gid to switch from root to
|
29
|
+
# @param [Hash] opts The options to create a observer with
|
30
|
+
# @option opts [Array<String>] :paths Additional paths to change
|
31
|
+
# ownership of.
|
32
|
+
# @option opts [String] :paths Additional path to to change
|
33
|
+
# ownership of
|
34
|
+
def initialize(user, group, opts={})
|
35
|
+
@path_set = Set.new(Array(opts[:paths]))
|
36
|
+
# Filter some default directories, plus any subdirectories of
|
37
|
+
# paths we discover at runtime
|
38
|
+
@filter_set = Set.new([%r(^/(etc|dev|sys|bin|sbin|etc|lib|lib64|boot|run|proc|selinux|tmp)(/|$))])
|
39
|
+
@user = user
|
40
|
+
@group = group
|
41
|
+
end
|
42
|
+
|
43
|
+
# Receives updates from FSMonitor#add_path
|
44
|
+
#
|
45
|
+
# @param [Hash] opts The options to update the observer
|
46
|
+
# @option opts [:symbol] :command The command to instruct the
|
47
|
+
# observer to execute.
|
48
|
+
# * +:add_path+ Indicates the +:data+ field contains a path.
|
49
|
+
# * +:stop_capture+ indicates that capturing has ceased. The
|
50
|
+
# observer will change ownership of the files, and switch
|
51
|
+
# to the user specified at #initialize.
|
52
|
+
# @option opts [String] :data Contains a resource path when the
|
53
|
+
# * +:add_path+ Command is called, otherwise ignored.
|
54
|
+
def update(update={})
|
55
|
+
case update[:command]
|
56
|
+
when :add_path
|
57
|
+
unless match_filter?(update[:data])
|
58
|
+
@path_set.add(update[:data])
|
59
|
+
@filter_set.merge(subdirectory_regex(update[:data]))
|
60
|
+
end
|
61
|
+
when :stop_capture, :chown
|
62
|
+
do_chown
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def do_chown
|
69
|
+
@path_set.each do |p|
|
70
|
+
FileUtils.chown_R(@user, @group, p, :force => true) if File.exist?(p)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def match_filter?(path)
|
75
|
+
@filter_set.inject(false){ |accum, filter| accum || !!(path =~ filter) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def subdirectory_regex(paths)
|
79
|
+
Array(paths).collect{ |p| Regexp.new("^#{p}/") }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2012 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 'tmpdir'
|
20
|
+
|
21
|
+
module BoxGrinder
|
22
|
+
class UserSwitcher
|
23
|
+
|
24
|
+
def UserSwitcher.change_user(u, g, &blk)
|
25
|
+
prev_u, prev_g = Process.uid, Process.gid
|
26
|
+
set_user(u, g)
|
27
|
+
blk.call
|
28
|
+
set_user(prev_u, prev_g)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Working around bugs.... we can rely on the saved id to be able
|
34
|
+
# to sneak back to the previous user later.
|
35
|
+
def UserSwitcher.set_user(u, g)
|
36
|
+
return if Process.uid == u && Process.gid == g
|
37
|
+
# If already set to the given value
|
38
|
+
Process.egid, Process.gid = g, g
|
39
|
+
Process.euid, Process.uid = u, u
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|