Anyway to trigger cleanups when classes are removed from a host?

68 views
Skip to first unread message

James Perry

unread,
Oct 4, 2017, 11:57:55 AM10/4/17
to Puppet Developers
Recently we have been changing out some software that was deployed via tarball extractions. Now we have a different app that deploys via RPM. To not break the legacy hosts where the new software doesn't we created a whole new class for deployments and setups on the new software.

I've Googled, dug through forum posts and looked into a lot f modules, but couldn't find anyway to make what i would like to see if it is possible to do. 

Is there a way do a cleanup on removing the class? Ideally it would be nice to have some way to cleanup as well as check to be sure it is cleaned up if it doesn't have the class. 

I tried to write a class to do something like this for a specific set of classes to see if host has them as part of their catalog. Somewhere deep in my memory I think I remember there being a way to access the classes using a built-in call, but can;t seem to find it. I know I can reference the /opt/puppetlabs/puppet/cache/state/classes.txt file, but i was trying to be sure that the data was accurate by pulling off the master. 

   Thanks! 

Rob Nelson

unread,
Oct 4, 2017, 12:14:11 PM10/4/17
to puppe...@googlegroups.com
Puppet enforces state. It does know about state you have not defined. So if you have a class that takes an ensure propert of absent, for instance, it can enforce that. But it cannot guess what “the absence of this class” means as a state model. Remember, your class model may say ‘make sure apache is installed’, but the actual state model will apply all the dependencies for apache. Turning that around to ‘make sure apache is NOT installed’ will not remove the dependencies that were installed. So no, there is no generic ‘absent’ value you can use to remove a class.

It is worth pointing out that immutable or ephemeral image patterns can help with this. In essence, you do not change the classification of an existing node, you delete that node and create a new node with the proper classification. No chance of any sort of cruft or manual configuration modifications persisting. Of course, that’s a goal most cannot fully approach, but it is something to aspire to. I don’t know what your classes are, but most people would not want to reclassify a database node as a web app node, or vice verse. They may be okay with reclassifying a web app node from application A to application B. There’s some value in those models even if you can’t implement them fully. 

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/ededc7b7-c4cd-4820-bd72-be9103753b72%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
Rob Nelson

James Perry

unread,
Oct 4, 2017, 8:36:03 PM10/4/17
to Puppet Developers
Thanks Rob.

As for reclassifying nodes that is a use case outside of what I'm trying to accomplish. 

Mostly I was trying to work more a scenario like the following: 

I have a set of restricted accounts for use with ERPM.on Linux. Each DBA is assigned a Linux local ERPM user that is the same on all hosts due to how ERPM is configured. Each of the ERPM account has specific sudo rules assigned to it using the sudoers module from Puppet Forge. Basically each erpm01-erpm30 user has the necessary groups, permissions, home and sudo rules for that account. Each user is a defined class so we can add individual ones on the host where they are required. I can't set the ERPMXX class to absent as that will remove it globally, which we don't want. I knew ways to work around this, but I'm trying to keep things as clean and simple as possible so we don't have to touch the code except to add new functionality. Our level on admins are given access in Foreman to add the class so they need not touch any code. 

-------------------------------------------------------------------

Based on your explanation, how can I query / access the state Puppet knows for a host with regard to classes it doesn't have assigned? 

I would like to write code to check for the absence of a class/classes and then tell puppet what I want it to mean when the class is absent. Using the example above, it would loop through all of the ERPMXX classes to detect those that aren't present. When one is found to not be present it would define the state noting for ensure => absent for that user. If the class is there it does nothing for that user. 

Do as you noted in your Example for Apache, packages to know to be installed solely for Apache dependencies could be defined and set ensure => "absent" and any other steps required to handle the absence of the class. 

I know i don't even have a partial grasp of the intricacies of the Puppet internals, so being able to check the state of classes being present or absent on the host other than from the host's classes.txt file. 

Thomas

unread,
Oct 5, 2017, 2:41:08 AM10/5/17
to puppe...@googlegroups.com
you could use the defined(Class[xy]) function to test if the class is included.

but be aware that you need to control the manifest parse order for that to work. if you check defined() before the class is included this wont work.

- Thomas

https://docs.puppet.com/puppet/latest/function.html#defined

Rob Nelson

unread,
Oct 5, 2017, 10:48:20 AM10/5/17
to puppe...@googlegroups.com
Ah, sudoers files. That narrows it down - less of a class issue and more of a multiple defined type instance issue. What module are you using, specifically? I use saz/sudo because it purges ALL sudoer.d files that it does not manage. So if on one run, there were say ERPM01-30 users and then on the next only ERPM01 and ERPM10-30 were present, ERPM02-09 would be automatically purged.

If I understand the problem correctly, I think your solution is to look at the module you're using to see if it has a method to purge non-managed sudoer.d files, and if not, look at adding that to the module or switching to a module like saz/sudo.

If I did not understand the problem, let me know. I think I have another idea, but best to see if I'm on the right track rather than confusing the issue :)

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/1dd6e4f0-fff1-41a8-bad3-7d502a8bae7a%40googlegroups.com.

James Perry

unread,
Oct 5, 2017, 1:35:10 PM10/5/17
to Puppet Developers
I'm using the saz/sudoers as well and it removes, say ERPM10-20, when I remove the user from the host, exactly as expected.

What doesn't happen is the user ERPM10-20 isn't removed from the server.

Let me try to see if I can put it another way to make it clearer. 

Say I have ERPM01-01, ERPM01-22 and ERPM02-09 defined. Here is a scenario.

Server Mapping:
ERPM01-01: servera, serverb, serverc
ERPM01-22: servera, serverc
ERPM02-09: serverb, serverc

ERPM User mapping to ERPM accounts based on AD credentials to access ERPM.  

ERPM01-01: Foo
ERPM01-22: Bar
ERPM02-09: Baz

So to get access to servera, serverb or serverc, Foo logs into ERPM with AD credentials. Then ERPM's hosting server then handles providing the username (ERPM01-01) to the host and the password. Foo never knows the password so they can't ever access the account outside of ERPM. 

Now Baz was supporting a DB on serverc, but is moved to another team. We get a request to remove ERPM02-09 from serverc. 

In Foreman we go to the host, pull that class off serverc.  Since Baz is still on serverb, we can't set ensure => absent on the Puppet user block in class ERPM02-09 as that will lock him out of serverb. When Puppet runs on serverc the sudoers module removes the sudoers.d/erpm02-09.conf file. 

Unfortunately the user ERPM02-09 is still on the host. 

What I wanted to code up would be to iterate through the ERPMXX-YY classes to see if any of the classes are absent. If so it then calls a user block to do ensure => absent for ERPM02-09 on serverc and servera while serverb will still have the user and sudoers definitions. 

What I don't know how to do is to find where I can access the Puppet state for classes which are absent. 

I hope this is a better explanation of what I'm trying to do here. 

Ryan Whitehurst

unread,
Oct 5, 2017, 1:45:59 PM10/5/17
to puppe...@googlegroups.com
If you're managing all the non-system users with puppet, you can use the resources type with purge, something like

resources { 'user':
  purge => true,
  unless_system_user => true,
}

 
What I don't know how to do is to find where I can access the Puppet state for classes which are absent. 


You can't, at least not safely or reliably. If you can't use the resources type with purge, the other option would be to have an "ensure" parameter on the class which propagates down to the underlying user resource and instead of removing the class, set that parameter to absent.
 
I hope this is a better explanation of what I'm trying to do here. 

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscribe@googlegroups.com.

James Perry

unread,
Oct 5, 2017, 2:31:43 PM10/5/17
to Puppet Developers


On Thursday, October 5, 2017 at 1:45:59 PM UTC-4, Ryan Whitehurst wrote:
On Thu, Oct 5, 2017 at 10:35 AM, James Perry <jjpe...@gmail.com> wrote:
I'm using the saz/sudoers as well and it removes, say ERPM10-20, when I remove the user from the host, exactly as expected.

What doesn't happen is the user ERPM10-20 isn't removed from the server.

Let me try to see if I can put it another way to make it clearer. 

Say I have ERPM01-01, ERPM01-22 and ERPM02-09 defined. Here is a scenario.

Server Mapping:
ERPM01-01: servera, serverb, serverc
ERPM01-22: servera, serverc
ERPM02-09: serverb, serverc

ERPM User mapping to ERPM accounts based on AD credentials to access ERPM.  

ERPM01-01: Foo
ERPM01-22: Bar
ERPM02-09: Baz

So to get access to servera, serverb or serverc, Foo logs into ERPM with AD credentials. Then ERPM's hosting server then handles providing the username (ERPM01-01) to the host and the password. Foo never knows the password so they can't ever access the account outside of ERPM. 

Now Baz was supporting a DB on serverc, but is moved to another team. We get a request to remove ERPM02-09 from serverc. 

In Foreman we go to the host, pull that class off serverc.  Since Baz is still on serverb, we can't set ensure => absent on the Puppet user block in class ERPM02-09 as that will lock him out of serverb. When Puppet runs on serverc the sudoers module removes the sudoers.d/erpm02-09.conf file. 

Unfortunately the user ERPM02-09 is still on the host. 

What I wanted to code up would be to iterate through the ERPMXX-YY classes to see if any of the classes are absent. If so it then calls a user block to do ensure => absent for ERPM02-09 on serverc and servera while serverb will still have the user and sudoers definitions. 


If you're managing all the non-system users with puppet, you can use the resources type with purge, something like

resources { 'user':
  purge => true,
  unless_system_user => true,
}

 

I looked at that as an option, but we have users on the server that aren't managed by puppet.
 
What I don't know how to do is to find where I can access the Puppet state for classes which are absent. 


You can't, at least not safely or reliably. If you can't use the resources type with purge, the other option would be to have an "ensure" parameter on the class which propagates down to the underlying user resource and instead of removing the class, set that parameter to absent.

This was one option I looked into this via a class parameter that would be overridden on the hosts were the class was assigned, but with 200+ hosts, that became tedious and error prone. 

 
I hope this is a better explanation of what I'm trying to do here. 

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.


Thanks for the input. I guess I'm back to my original thoughts of making a script that looks for all ERPM* user accounts to check them against the puppet resource user output. Any that don't have a resource entry are removed from the host.

The overrides work, but don't scale up well. 

As these hosts are using ERPM for user access compliance audits, I need to work out a way to clean that specific set out without squishing any other users. I had hoped get lucky and find there was a hidden way to trigger puppet to do specific actions when a class is no longer present on the next time compiles the catalog. 
Reply all
Reply to author
Forward
0 new messages