ruby-augeas 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +510 -0
- data/NEWS +18 -0
- data/README.rdoc +34 -0
- data/Rakefile +132 -0
- data/ext/augeas/_augeas.c +445 -0
- data/ext/augeas/extconf.rb +30 -0
- data/lib/augeas.rb +119 -0
- data/tests/root/etc/group +26 -0
- data/tests/root/etc/hosts +6 -0
- data/tests/root/etc/inittab +53 -0
- data/tests/root/etc/ssh/sshd_config +2 -0
- data/tests/tc_augeas.rb +208 -0
- metadata +80 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
##
|
2
|
+
# extconf.rb: Ruby extension configuration
|
3
|
+
#
|
4
|
+
# Copyright (C) 200 Red Hat Inc.
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License as published by the Free Software Foundation; either
|
9
|
+
# version 2.1 of the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This library is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this library; if not, write to the Free Software
|
18
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
# Author: Bryan Kearney <bkearney@redhat.com>
|
21
|
+
##
|
22
|
+
require 'mkmf'
|
23
|
+
|
24
|
+
extension_name = '_augeas'
|
25
|
+
|
26
|
+
unless pkg_config("augeas")
|
27
|
+
raise "augeas-devel not installed"
|
28
|
+
end
|
29
|
+
|
30
|
+
create_makefile(extension_name)
|
data/lib/augeas.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
##
|
2
|
+
# augeas.rb: Ruby wrapper for augeas
|
3
|
+
#
|
4
|
+
# Copyright (C) 2008 Red Hat Inc.
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License as published by the Free Software Foundation; either
|
9
|
+
# version 2.1 of the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This library is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this library; if not, write to the Free Software
|
18
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
# Author: Bryan Kearney <bkearney@redhat.com>
|
21
|
+
##
|
22
|
+
|
23
|
+
require "_augeas"
|
24
|
+
|
25
|
+
# Wrapper class for the augeas[http://augeas.net] library.
|
26
|
+
class Augeas
|
27
|
+
private_class_method :new
|
28
|
+
|
29
|
+
class Error < RuntimeError; end
|
30
|
+
|
31
|
+
# Create a new Augeas instance and return it.
|
32
|
+
#
|
33
|
+
# Use +root+ as the filesystem root. If +root+ is +nil+, use the value
|
34
|
+
# of the environment variable +AUGEAS_ROOT+. If that doesn't exist
|
35
|
+
# either, use "/".
|
36
|
+
#
|
37
|
+
# +loadpath+ is a colon-spearated list of directories that modules
|
38
|
+
# should be searched in. This is in addition to the standard load path
|
39
|
+
# and the directories in +AUGEAS_LENS_LIB+
|
40
|
+
#
|
41
|
+
# +flags+ is a bitmask (see <tt>enum aug_flags</tt>)
|
42
|
+
#
|
43
|
+
# When a block is given, the Augeas instance is passed as the only
|
44
|
+
# argument into the block and closed when the block exits. In that
|
45
|
+
# case, the return value of the block is the return value of
|
46
|
+
# +open+. With no block, the Augeas instance is returned.
|
47
|
+
def self.open(root = nil, loadpath = nil, flags = NONE, &block)
|
48
|
+
aug = open3(root, loadpath, flags)
|
49
|
+
if block_given?
|
50
|
+
begin
|
51
|
+
rv = yield aug
|
52
|
+
return rv
|
53
|
+
ensure
|
54
|
+
aug.close
|
55
|
+
end
|
56
|
+
else
|
57
|
+
return aug
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Set one or multiple elemens to path.
|
62
|
+
# Multiple elements are mainly sensible with a path like
|
63
|
+
# .../array[last()+1], since this will append all elements.
|
64
|
+
def set(path, *values)
|
65
|
+
values.flatten.each { |v| set_internal(path, v) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# The same as +set+, but raises <tt>Augeas::Error</tt> if setting fails
|
69
|
+
def set!(path, *values)
|
70
|
+
values.flatten.each do |v|
|
71
|
+
raise Augeas::Error unless set_internal(path, v)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Clear the +path+, i.e. make its value +nil+
|
76
|
+
def clear(path)
|
77
|
+
set_internal(path, nil)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Clear all transforms under <tt>/augeas/load</tt>. If +load+
|
81
|
+
# is called right after this, there will be no files
|
82
|
+
# under +/files+
|
83
|
+
def clear_transforms
|
84
|
+
rm("/augeas/load/*")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Add a transform under <tt>/augeas/load</tt>
|
88
|
+
#
|
89
|
+
# The HASH can contain the following entries
|
90
|
+
# * <tt>:lens</tt> - the name of the lens to use
|
91
|
+
# * <tt>:name</tt> - a unique name; use the module name of the LENS when omitted
|
92
|
+
# * <tt>:incl</tt> - a list of glob patterns for the files to transform
|
93
|
+
# * <tt>:excl</tt> - a list of the glob patterns to remove from the list that matches <tt>:INCL</tt>
|
94
|
+
def transform(hash)
|
95
|
+
lens = hash[:lens]
|
96
|
+
name = hash[:name]
|
97
|
+
incl = hash[:incl]
|
98
|
+
excl = hash[:excl]
|
99
|
+
raise ArgumentError, "No lens specified" unless lens
|
100
|
+
raise ArgumentError, "No files to include" unless incl
|
101
|
+
name = lens.split(".")[0].sub("@", "") unless name
|
102
|
+
|
103
|
+
xfm = "/augeas/load/#{name}/"
|
104
|
+
set(xfm + "lens", lens)
|
105
|
+
set(xfm + "incl[last()+1]", incl)
|
106
|
+
set(xfm + "excl[last()+1]", excl) if excl
|
107
|
+
end
|
108
|
+
|
109
|
+
# The same as +save+, but raises <tt>Augeas::Error</tt> if saving fails
|
110
|
+
def save!
|
111
|
+
raise Augeas::Error unless save
|
112
|
+
end
|
113
|
+
|
114
|
+
# The same as +load+, but raises <tt>Augeas::Error</tt> if loading fails
|
115
|
+
def load!
|
116
|
+
raise Augeas::Error unless load
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
root:x:0:root
|
2
|
+
bin:x:1:root,bin,daemon
|
3
|
+
daemon:x:2:root,bin,daemon
|
4
|
+
sys:x:3:root,bin,adm
|
5
|
+
adm:x:4:root,adm,daemon
|
6
|
+
tty:x:5:
|
7
|
+
disk:x:6:root
|
8
|
+
lp:x:7:daemon,lp
|
9
|
+
mem:x:8:
|
10
|
+
kmem:x:9:
|
11
|
+
wheel:x:10:root
|
12
|
+
mail:x:12:mail,postfix
|
13
|
+
uucp:x:14:uucp
|
14
|
+
man:x:15:
|
15
|
+
games:x:20:
|
16
|
+
gopher:x:30:
|
17
|
+
dip:x:40:
|
18
|
+
ftp:x:50:
|
19
|
+
lock:x:54:
|
20
|
+
nobody:x:99:
|
21
|
+
users:x:100:
|
22
|
+
floppy:x:19:
|
23
|
+
vcsa:x:69:
|
24
|
+
rpc:x:32:asfd
|
25
|
+
rpcuser:x:29:
|
26
|
+
nfsnobody:x:499:
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Do not remove the following line, or various programs
|
2
|
+
# that require network functionality will fail.
|
3
|
+
127.0.0.1 localhost.localdomain localhost galia.watzmann.net galia
|
4
|
+
#172.31.122.254 granny.watzmann.net granny puppet
|
5
|
+
#172.31.122.1 galia.watzmann.net galia
|
6
|
+
172.31.122.14 orange.watzmann.net orange
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# inittab This file describes how the INIT process should set up
|
3
|
+
# the system in a certain run-level.
|
4
|
+
#
|
5
|
+
# Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
|
6
|
+
# Modified for RHS Linux by Marc Ewing and Donnie Barnes
|
7
|
+
#
|
8
|
+
|
9
|
+
# Default runlevel. The runlevels used by RHS are:
|
10
|
+
# 0 - halt (Do NOT set initdefault to this)
|
11
|
+
# 1 - Single user mode
|
12
|
+
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
|
13
|
+
# 3 - Full multiuser mode
|
14
|
+
# 4 - unused
|
15
|
+
# 5 - X11
|
16
|
+
# 6 - reboot (Do NOT set initdefault to this)
|
17
|
+
#
|
18
|
+
id:5:initdefault:
|
19
|
+
|
20
|
+
# System initialization.
|
21
|
+
si::sysinit:/etc/rc.d/rc.sysinit
|
22
|
+
|
23
|
+
l0:0:wait:/etc/rc.d/rc 0
|
24
|
+
l1:1:wait:/etc/rc.d/rc 1
|
25
|
+
l2:2:wait:/etc/rc.d/rc 2
|
26
|
+
l3:3:wait:/etc/rc.d/rc 3
|
27
|
+
l4:4:wait:/etc/rc.d/rc 4
|
28
|
+
l5:5:wait:/etc/rc.d/rc 5
|
29
|
+
l6:6:wait:/etc/rc.d/rc 6
|
30
|
+
|
31
|
+
# Trap CTRL-ALT-DELETE
|
32
|
+
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
|
33
|
+
|
34
|
+
# When our UPS tells us power has failed, assume we have a few minutes
|
35
|
+
# of power left. Schedule a shutdown for 2 minutes from now.
|
36
|
+
# This does, of course, assume you have powerd installed and your
|
37
|
+
# UPS connected and working correctly.
|
38
|
+
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
|
39
|
+
|
40
|
+
# If power was restored before the shutdown kicked in, cancel it.
|
41
|
+
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
|
42
|
+
|
43
|
+
|
44
|
+
# Run gettys in standard runlevels
|
45
|
+
1:2345:respawn:/sbin/mingetty tty1
|
46
|
+
2:2345:respawn:/sbin/mingetty tty2
|
47
|
+
3:2345:respawn:/sbin/mingetty tty3
|
48
|
+
4:2345:respawn:/sbin/mingetty tty4
|
49
|
+
5:2345:respawn:/sbin/mingetty tty5
|
50
|
+
6:2345:respawn:/sbin/mingetty tty6
|
51
|
+
|
52
|
+
# Run xdm in runlevel 5
|
53
|
+
x:5:respawn:/etc/X11/prefdm -nodaemon
|
data/tests/tc_augeas.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
TOPDIR = File::expand_path(File::join(File::dirname(__FILE__), ".."))
|
4
|
+
|
5
|
+
$:.unshift(File::join(TOPDIR, "lib"))
|
6
|
+
$:.unshift(File::join(TOPDIR, "ext", "augeas"))
|
7
|
+
|
8
|
+
require 'augeas'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
class TestAugeas < Test::Unit::TestCase
|
12
|
+
|
13
|
+
SRC_ROOT = File::expand_path(File::join(TOPDIR, "tests", "root")) + "/."
|
14
|
+
TST_ROOT = File::expand_path(File::join(TOPDIR, "build", "root")) + "/"
|
15
|
+
|
16
|
+
def test_basics
|
17
|
+
aug = aug_open(Augeas::SAVE_NEWFILE)
|
18
|
+
assert_equal("newfile", aug.get("/augeas/save"))
|
19
|
+
assert_equal(TST_ROOT, aug.get("/augeas/root"))
|
20
|
+
|
21
|
+
assert(aug.exists("/augeas/root"))
|
22
|
+
assert_not_nil(aug.get("/augeas/root"))
|
23
|
+
node = "/ruby/test/node"
|
24
|
+
assert_nothing_raised {
|
25
|
+
aug.set(node, "value")
|
26
|
+
}
|
27
|
+
assert_equal("value", aug.get(node))
|
28
|
+
assert_nothing_raised {
|
29
|
+
aug.clear(node)
|
30
|
+
}
|
31
|
+
assert_equal(nil, aug.get(node))
|
32
|
+
m = aug.match("/*")
|
33
|
+
["/augeas", "/ruby"].each do |p|
|
34
|
+
assert(m.include?(p))
|
35
|
+
assert(aug.exists(p))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_no_new
|
40
|
+
assert_raise NoMethodError do
|
41
|
+
Augeas.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_close
|
46
|
+
aug = Augeas::open("/tmp", nil, Augeas::SAVE_NEWFILE)
|
47
|
+
assert_equal("newfile", aug.get("/augeas/save"))
|
48
|
+
aug.close
|
49
|
+
|
50
|
+
assert_raise(SystemCallError) {
|
51
|
+
aug.get("/augeas/save")
|
52
|
+
}
|
53
|
+
|
54
|
+
assert_raise(SystemCallError) {
|
55
|
+
aug.close
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_mv
|
60
|
+
Augeas::open("/dev/null") do |aug|
|
61
|
+
aug.set("/a/b", "value")
|
62
|
+
aug.mv("/a/b", "/x/y")
|
63
|
+
assert_equal("value", aug.get("/x/y"))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_load
|
68
|
+
aug = aug_open(Augeas::NO_LOAD)
|
69
|
+
assert_equal([], aug.match("/files/etc/*"))
|
70
|
+
aug.rm("/augeas/load/*");
|
71
|
+
assert_nothing_raised {
|
72
|
+
aug.load
|
73
|
+
}
|
74
|
+
assert_equal([], aug.match("/files/etc/*"))
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_transform
|
78
|
+
aug = aug_open(Augeas::NO_LOAD)
|
79
|
+
aug.clear_transforms
|
80
|
+
aug.transform(:lens => "Hosts.lns",
|
81
|
+
:incl => "/etc/hosts")
|
82
|
+
assert_raise(ArgumentError) {
|
83
|
+
aug.transform(:name => "Fstab",
|
84
|
+
:incl => [ "/etc/fstab" ],
|
85
|
+
:excl => [ "*~", "*.rpmnew" ])
|
86
|
+
}
|
87
|
+
aug.transform(:lens => "Inittab.lns",
|
88
|
+
:incl => "/etc/inittab")
|
89
|
+
aug.transform(:lens => "Fstab.lns",
|
90
|
+
:incl => "/etc/fstab*",
|
91
|
+
:excl => "*~")
|
92
|
+
assert_equal(["/augeas/load/Fstab", "/augeas/load/Fstab/excl",
|
93
|
+
"/augeas/load/Fstab/incl", "/augeas/load/Fstab/lens",
|
94
|
+
"/augeas/load/Hosts", "/augeas/load/Hosts/incl",
|
95
|
+
"/augeas/load/Hosts/lens", "/augeas/load/Inittab",
|
96
|
+
"/augeas/load/Inittab/incl",
|
97
|
+
"/augeas/load/Inittab/lens"],
|
98
|
+
aug.match("/augeas/load//*").sort)
|
99
|
+
aug.load
|
100
|
+
assert_equal(["/files/etc/hosts", "/files/etc/inittab"],
|
101
|
+
aug.match("/files/etc/*").sort)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_defvar
|
105
|
+
Augeas::open("/dev/null") do |aug|
|
106
|
+
aug.set("/a/b", "bval")
|
107
|
+
aug.set("/a/c", "cval")
|
108
|
+
assert aug.defvar("var", "/a/b")
|
109
|
+
assert_equal(["/a/b"], aug.match("$var"))
|
110
|
+
assert aug.defvar("var", nil)
|
111
|
+
assert_raises(SystemCallError) {
|
112
|
+
aug.match("$var")
|
113
|
+
}
|
114
|
+
assert ! aug.defvar("var", "/foo/")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_defnode
|
119
|
+
aug = aug_open
|
120
|
+
assert aug.defnode("x", "/files/etc/hosts/*[ipaddr = '127.0.0.1']", nil)
|
121
|
+
assert_equal(["/files/etc/hosts/1"], aug.match("$x"))
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_save!
|
125
|
+
aug = aug_open
|
126
|
+
aug.set("/files/etc/hosts/1/garbage", "trash")
|
127
|
+
assert_raises(Augeas::Error) { aug.save! }
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_set!
|
131
|
+
aug = aug_open
|
132
|
+
assert_raises(Augeas::Error) { aug.set!("files/etc/hosts/*", nil) }
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_set
|
136
|
+
aug = aug_open
|
137
|
+
aug.set("/files/etc/group/disk/user[last()+1]",["user1","user2"])
|
138
|
+
assert_equal( aug.get("/files/etc/group/disk/user[1]"),"root" )
|
139
|
+
assert_equal( aug.get("/files/etc/group/disk/user[2]"),"user1" )
|
140
|
+
assert_equal( aug.get("/files/etc/group/disk/user[3]"),"user2" )
|
141
|
+
|
142
|
+
aug.set("/files/etc/group/new_group/user[last()+1]",
|
143
|
+
"nuser1",["nuser2","nuser3"])
|
144
|
+
assert_equal( aug.get("/files/etc/group/new_group/user[1]"),"nuser1")
|
145
|
+
assert_equal( aug.get("/files/etc/group/new_group/user[2]"),"nuser2" )
|
146
|
+
assert_equal( aug.get("/files/etc/group/new_group/user[3]"),"nuser3" )
|
147
|
+
|
148
|
+
aug.rm("/files/etc/group/disk/user")
|
149
|
+
aug.set("/files/etc/group/disk/user[last()+1]","testuser")
|
150
|
+
assert_equal( aug.get("/files/etc/group/disk/user"),"testuser")
|
151
|
+
|
152
|
+
aug.rm("/files/etc/group/disk/user")
|
153
|
+
aug.set("/files/etc/group/disk/user[last()+1]", nil)
|
154
|
+
assert_equal( aug.get("/files/etc/group/disk/user"), nil)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_setm
|
158
|
+
aug = aug_open
|
159
|
+
|
160
|
+
aug.setm("/files/etc/group/*[label() =~ regexp(\"rpc.*\")]","users", "testuser1")
|
161
|
+
assert_equal( aug.get("/files/etc/group/rpc/users"), "testuser1")
|
162
|
+
assert_equal( aug.get("/files/etc/group/rpcuser/users"), "testuser1")
|
163
|
+
|
164
|
+
aug.setm("/files/etc/group/*[label() =~ regexp(\"rpc.*\")]/users",nil, "testuser2")
|
165
|
+
assert_equal( aug.get("/files/etc/group/rpc/users"), "testuser2")
|
166
|
+
assert_equal( aug.get("/files/etc/group/rpcuser/users"), "testuser2")
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_error
|
170
|
+
aug = aug_open
|
171
|
+
|
172
|
+
# Cause an error
|
173
|
+
aug.get("/files/etc/hosts/*")
|
174
|
+
err = aug.error
|
175
|
+
assert_equal(Augeas::EMMATCH, err[:code])
|
176
|
+
assert err[:message]
|
177
|
+
assert err[:details]
|
178
|
+
assert err[:minor].nil?
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_span
|
182
|
+
aug = aug_open
|
183
|
+
|
184
|
+
span = aug.span("/files/etc/ssh/sshd_config/Protocol")
|
185
|
+
assert_equal({}, span)
|
186
|
+
|
187
|
+
aug.set("/augeas/span", "enable")
|
188
|
+
aug.rm("/files/etc")
|
189
|
+
aug.load
|
190
|
+
|
191
|
+
span = aug.span("/files/etc/ssh/sshd_config/Protocol")
|
192
|
+
assert_not_nil(span[:filename])
|
193
|
+
assert_equal(29..37, span[:label])
|
194
|
+
assert_equal(38..39, span[:value])
|
195
|
+
assert_equal(29..40, span[:span])
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
def aug_open(flags = Augeas::NONE)
|
200
|
+
if File::directory?(TST_ROOT)
|
201
|
+
FileUtils::rm_rf(TST_ROOT)
|
202
|
+
end
|
203
|
+
FileUtils::mkdir_p(TST_ROOT)
|
204
|
+
FileUtils::cp_r(SRC_ROOT, TST_ROOT)
|
205
|
+
|
206
|
+
Augeas::open(TST_ROOT, nil, flags)
|
207
|
+
end
|
208
|
+
end
|