boxgrinder-build 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|