ruby-augeas 0.4.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/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
|