augeas type and /etc/services

733 views
Skip to first unread message

Christopher Johnston

unread,
Jun 2, 2010, 4:03:25 PM6/2/10
to puppet...@googlegroups.com
Has anyone attempted to use the augeas type to add a service?  I got the service to add no problem, but having some difficulties to get the match to work to prevent duplicate entries from adding.  Since the service-name[*] has endless number of entries I used a glob so it checks all the entries but that does not seem to work.  Any ideas on how to proceed?

  augeas { app_tcp':
    context => '/files/etc/services',
    changes => ['insert service-name after service-name[last()]',
                'set service-name[last()] app_tcp',
                'set service-name[last()]/port 1002',
                'set service-name[last()]/protocol tcp'],
    onlyif  => "match service-name[.*] != '[port = 1002][protocol = tcp]'"
  }



Rob McBroom

unread,
Jun 2, 2010, 10:59:09 PM6/2/10
to puppet...@googlegroups.com

I'm no expert, but I've messed with Augeas a bit and you can make it harder than it needs to be without even trying. I haven't done anything in `/etc/services`, but I had a similar issue with `sudoers`. A trick to keep in mind is that if you set something on a path that doesn't exist, Augeas will create it. So, if you can find something that makes an item unique, you can use that to specify a path. In this case, the port number will probably work.

augeas { 'app_tcp':
context => '/files/etc/services',
changes => [

"set /files/etc/services/service-name[port = '1002']/port 1002"
"set /files/etc/services/service-name[port = '1002'] app_tcp"
"set /files/etc/services/service-name[port = '1002']/protocol tcp"
"set /files/etc/services/service-name[port = '1002']/#comment foo"
],
}

This should create the line in `/etc/services` if it doesn't exist, but if it does exist and nothing has changed, Puppet won't do anything to the line (which is generally what you want). Setting the “name” doesn't seem to work until after the thing exists, which is why it appears second on the list.

--
Rob McBroom
<http://www.skurfer.com/>

It's not that I think guns, drugs, prostitution, swimming, eating and reading should be legal. It's just that no one on Earth has the authority to make them illegal.


Christopher Johnston

unread,
Jun 3, 2010, 12:04:15 PM6/3/10
to puppet...@googlegroups.com
# puppet -ddd foo1.pp
Could not parse for environment production: Syntax error at 'set /files/etc/services/service-name[port = '1002'] app_tcp'; expected ']' at /data/foo1.pp:5


I don't believe that works...



--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.


Christopher Johnston

unread,
Jun 3, 2010, 12:20:40 PM6/3/10
to puppet...@googlegroups.com
Duh sorry I added commas for the array... stil the same error.  I dont think that will work since the entries in the services file are usually like this:

augtool> print /files/etc/services/service-name[1]
/files/etc/services/service-name[1] = "tcpmux"
/files/etc/services/service-name[1]/port = "1"
/files/etc/services/service-name[1]/protocol = "tcp"
/files/etc/services/service-name[1]/#comment = "TCP port service multiplexer"

So for the heck of it I replaced the [port = 1002] with something like 0000000001 and that just ended up replacing the first entry in the file (by removing it).  So still not the behavior I am looking for.  I should be able to append to the bottom of the file but have onlyif() sort through the entire file and verify a match.

Any other ideas?

Rob McBroom

unread,
Jun 3, 2010, 12:57:42 PM6/3/10
to puppet...@googlegroups.com
On Jun 3, 2010, at 12:04 PM, Christopher Johnston wrote:

> # puppet -ddd foo1.pp
> Could not parse for environment production: Syntax error at 'set /files/etc/services/service-name[port = '1002'] app_tcp'; expected ']' at /data/foo1.pp:5

It looks like you're trying to use single-quotes (for the port number) inside of single-quotes (for the entire set statement). You'll have to use double-quotes in one place or the other, or escaping the inner single-quotes might also work.

I tested it using `augtool`, so it works. It's just a matter of translating it and quoting it correctly for Puppet.

Christopher Johnston

unread,
Jun 3, 2010, 1:40:21 PM6/3/10
to puppet...@googlegroups.com
I tried mixing/matching quotes, if I double quote just the set statement and quote nothing else it goes through but nothing gets changed.

for eg: "set service-name[port = 7302]/port 7302",

"debug: Augeas[cti-p01-dgw_udp](provider=augeas): Skipping becuase no files were changed"

Now if I single quote the port number in the [] I get another error.. which likely means using the '' is not correct. 

err: //Augeas[cti-p01-dgw_tcp]/returns: change from need_to_run to 0 failed: Save failed with return code false

Getting closer...

Rob McBroom

unread,
Jun 3, 2010, 1:59:19 PM6/3/10
to puppet...@googlegroups.com
On Jun 3, 2010, at 1:40 PM, Christopher Johnston wrote:

> Now if I single quote the port number in the [] I get another error.. which likely means using the '' is not correct.
>
> err: //Augeas[cti-p01-dgw_tcp]/returns: change from need_to_run to 0 failed: Save failed with return code false

Ah, then I suspect you're using 0.24.x.

http://projects.reductivelabs.com/issues/2141

I wouldn't even bother with Augeas until you go to 0.25.x where this bug was fixed.

Christopher Johnston

unread,
Jun 3, 2010, 2:19:04 PM6/3/10
to puppet...@googlegroups.com
I am on 25.4...

Rob McBroom

unread,
Jun 3, 2010, 2:40:40 PM6/3/10
to puppet...@googlegroups.com
You had to make me actually try it in Puppet, huh? ;)

My original example was missing commas after the various set statements. Not sure if you fixed that. It also specified the full path, even though the context should have taken care of most of it. That didn't seem to hurt, but to be safe, I took it out. I'm also using 0.25.4 and this worked:

augeas { 'app_tcp':
context => '/files/etc/services',
changes => [

"set service-name[port = '1002']/port 1002",
"set service-name[port = '1002'] app_tcp",
"set service-name[port = '1002']/protocol tcp",
# "set service-name[port = '1002']/#comment foo",
],
}

I disabled the comment because the line ended up looking like this:

app_tcp 1002/tcp# foo

But that's probably a bug in the Agueas lens, not Puppet.

Christopher Johnston

unread,
Jun 3, 2010, 3:05:46 PM6/3/10
to puppet...@googlegroups.com
HA, yes I added commas.  You know what the problem was, my ordering.  I had app_tcp first and not port 1002 so thats likely why it was not getting picked up.  Worked, but hit another snag.  Now try adding another app name, same port but for udp, it will just get overwritten. 

-Chris


Rob McBroom

unread,
Jun 3, 2010, 10:55:18 PM6/3/10
to puppet...@googlegroups.com
On Jun 3, 2010, at 3:05 PM, Christopher Johnston wrote:

> You know what the problem was, my ordering. I had app_tcp first and not port 1002 so thats likely why it was not getting picked up. Worked, but hit another snag. Now try adding another app name, same port but for udp, it will just get overwritten.

I addressed both of those things in my initial reply.

On the order of `set` statements:

> Setting the “name” doesn't seem to work until after the thing exists, which is why it appears second on the list.

On adding both TCP and UDP entries:

> So, if you can find something that makes an item unique, you can use that to specify a path.

If two entries are using the same port number, that obviously won't work as a unique identifier. You could maybe use a unique comment on each one, but there seems to be that bug where no space appears between protocol and comment. Perhaps there's a way to specify a path using more than one component. A combination of port and protocol should be unique, for example.

Christopher Johnston

unread,
Jun 4, 2010, 10:20:06 AM6/4/10
to puppet...@googlegroups.com
I tried using the "alias" option as an identifier, but have not been succesful with it.  I will play that a little bit more as I think that may be the only way to do it that I know of.

Rob McBroom

unread,
Jun 4, 2010, 10:33:43 AM6/4/10
to puppet...@googlegroups.com
On Jun 4, 2010, at 10:20 AM, Christopher Johnston wrote:

> I tried using the "alias" option as an identifier, but have not been succesful with it. I will play that a little bit more as I think that may be the only way to do it that I know of.

It looks like you can use the port/protocol combination. At least it works for printing. I haven't tested it to create a new entry.

augtool> print /files/etc/services/service-name[port = '443'][protocol = 'tcp']
/files/etc/services/service-name[161] = "https"
/files/etc/services/service-name[161]/port = "443"
/files/etc/services/service-name[161]/protocol = "tcp"
/files/etc/services/service-name[161]/#comment = "MCom"

--
Rob McBroom
<http://www.skurfer.com/>

Don't try to tell me something is important to you if the whole of your “support” entails getting Congress to force *others* to spend time and money on it.

Rob McBroom

unread,
Jun 4, 2010, 10:42:55 AM6/4/10
to puppet...@googlegroups.com
These types of paths seem to match the correct thing as well:

/files/etc/services/service-name[port = '443' and protocol = 'tcp']
/files/etc/services/*[port = '443' and protocol = 'tcp']

Maybe you should just take a look at <http://augeas.net/page/Path_expressions>.

Christopher Johnston

unread,
Jun 4, 2010, 11:09:39 AM6/4/10
to puppet...@googlegroups.com
Let me give this a whirl will let you know how I make out

Christopher Johnston

unread,
Jun 4, 2010, 11:55:16 AM6/4/10
to puppet...@googlegroups.com
What version of augeas are you using?  I am on 0.5.3 I don't think support has been added to do some of that functionality I am going to upgrade


--

Rob McBroom

unread,
Jun 4, 2010, 12:58:24 PM6/4/10
to puppet...@googlegroups.com
On Jun 4, 2010, at 11:55 AM, Christopher Johnston wrote:

> What version of augeas are you using? I am on 0.5.3 I don't think support has been added to do some of that functionality I am going to upgrade

0.7.0

Christopher Johnston

unread,
Jun 4, 2010, 1:03:00 PM6/4/10
to puppet...@googlegroups.com
I tested the new version from the CLI, I noticed it is quite different and more powerful features.  But I wonder if puppet has caught to support them in the augeas provider.  If I set this below it fails and either operation. 

    changes => ["set service-name[port = '7302'][protocol = 'tcp']/port 7302",

or

    changes => ["set service-name[port = '7302' and protocol = 'tcp']/port 7302",

Rob McBroom

unread,
Jun 4, 2010, 1:16:39 PM6/4/10
to puppet...@googlegroups.com
On Jun 4, 2010, at 1:03 PM, Christopher Johnston wrote:

> I tested the new version from the CLI, I noticed it is quite different and more powerful features. But I wonder if puppet has caught to support them in the augeas provider. If I set this below it fails and either operation.

Be sure to update augeas-libs and ruby-augeas too. (Those are the names of the packages from EPEL. You may have them under different names.) Puppet doesn't use `augtool`.

Christopher Johnston

unread,
Jun 4, 2010, 1:47:12 PM6/4/10
to puppet...@googlegroups.com
Yup, I am on the latest and greatest as well as an attempted git checkout of ruby-augeas, still no good.  Also on the latest .25.5 stable of puppet.   

ruby-augeas-0.3.0-1.fc10.x86_64
augeas-0.7.1-1.fc10.x86_64
augeas-libs-0.7.1-1.fc10.x86_64


Matt Juszczak

unread,
Jun 4, 2010, 3:32:29 PM6/4/10
to puppet...@googlegroups.com
Our DNS naming scheme works like this:

servername.<data center>.host-name.net

I'd like to be able to create a single server image with puppet configured
that can work with multiple data centers. Right now, my image is tied to
a single data center, so /etc/resolv.conf looks like this:

nameserver 1.2.3.4
nameserver 1.2.3.5
search iad01.host-name.net

The issue there is if I decide to use this image in a different data
center, which would have its own puppet instance setup.

So just to standardize, what I've been thinking of doing instead is
creating a "fake" data center, where CNAMEs live for other data centers,
such as:

launch.host-name.net

So we'd have:

nameserver 1.2.3.4
nameserver 1.2.3.5
search launch.host-name.net

That way, when puppet searches for "puppet" as a shortname (which it does
by default), it will try to connect to puppet.launch.host-name.net, which
is a central host. After it receives it's appropriate /etc/resolv.conf,
which will include data center specific things in it, I'll have that
puppetmaster instance restart puppet, which will then point it to its
local puppet instance....

Would this work? Assuming the same certificate was on both puppetmaster
servers?

Or is this asking for trouble?

-Matt

Mathias Gug

unread,
Jun 4, 2010, 3:45:01 PM6/4/10
to puppet...@googlegroups.com
On Fri, Jun 04, 2010 at 03:32:29PM -0400, Matt Juszczak wrote:
>
> So just to standardize, what I've been thinking of doing instead is
> creating a "fake" data center, where CNAMEs live for other data
> centers, such as:
>
>
> That way, when puppet searches for "puppet" as a shortname (which it
> does by default),

Why not use DNS views? In each of your data center puppet resolves to the local
puppetmaster.

--
Mathias Gug
Ubuntu Developer http://www.ubuntu.com

Nigel Kersten

unread,
Jun 4, 2010, 3:37:49 PM6/4/10
to puppet...@googlegroups.com
Can't you use a DNS view that simply resolves differently for different data centers? 

Reply all
Reply to author
Forward
0 new messages