I have a situation where I''d like to perform some actions when a node is removed from a class. I have a few (homegrown) services that install ssh keys in authorized_keys and it''s possible that a node may have the service enabled and disabled during it''s lifetime. When disabled I''d like to clean up the ssh keys for security reasons. This brings up the broader question in my mind of what it means for a node NOT to be in a class. I could see a scenario in the future where I want to, for instance, change a web server to a mail server. If I change "node myhost1 { include webserver }" to "node myhost1 { include mailserver }" what should happen? And if I have another class "ldapserver" in my configs that''s not listed under myhost1, should that class guarantee that myhost1 doesn''t run ldap even though I never assigned it to the node? Should I have classes like "not_webserver" and wield them on a temporary basis when repurposing hosts? That seems awfully imperative (boo!). Coming back to my ssh key problem, I tried including statements at the beginning of the class file outside the class definition for the service that removes the keys if the class is not assigned: $key = ''big long ssh key'' case tagged("sshkey_service"){ false: { replace_line { rmkey: file => ''authorized_keys", search => $key, replace => "" } <other stuff related to the service> } } class sshkey_service { append_if_no_such_line { mkkey: file => "authorized_keys", line => $key, require => File["authorized_keys"] } <other stuff related to the service > } node mr_no_service { } node mr_service { include sshkey_service } (The components are from the cookbook.) Unfortunately since nodes seem to be linked to classes last in the parsing (from my reading of prior posts) the replace_line() is always run. I''m open to alternate syntax suggestions. I saw a proposal about the iptables config to set it up as a template and conditionally include each line based on whether the node was tagged but I don''t like that as it puts my config information in two places. I like keeping the key with the service. What might be cool are class destructors where if a class with a suffix eg "_destructor" exists then every node that does not include the main class has the destructor run. Something like: class a_file { file { "/a_file": ensure => present } } class a_file_destructor { file { "/a_file": ensure => absent } } node with_a_file { include a_file } node without_a_file { } Matt Collins
On Nov 15, 2006, at 5:51 PM, matt wrote:> I have a situation where I''d like to perform some actions when a > node is > removed from a class. I have a few (homegrown) services that > install ssh > keys in authorized_keys and it''s possible that a node may have the > service enabled and disabled during it''s lifetime. When disabled I''d > like to clean up the ssh keys for security reasons. > > This brings up the broader question in my mind of what it means for a > node NOT to be in a class. I could see a scenario in the future > where I > want to, for instance, change a web server to a mail server. If I > change > "node myhost1 { include webserver }" to "node myhost1 { include > mailserver }" what should happen? And if I have another class > "ldapserver" in my configs that''s not listed under myhost1, should > that > class guarantee that myhost1 doesn''t run ldap even though I never > assigned it to the node? Should I have classes like "not_webserver" > and > wield them on a temporary basis when repurposing hosts? That seems > awfully imperative (boo!).I''ve been thinking about this exact scenario. I think a Purge at the class level, which applies whatever "purge" means to all of the children and contents of the class, is what would need to happen... I can see that being a huge can of worms though, I wonder what Luke thinks. Currently my solution for this is to just automate the rebuild the machine. Perhaps this is better (at least cleaner) in the long-run anyway. -Blake
Blake Barnett wrote:> > I''ve been thinking about this exact scenario. I think a Purge at the > class level, which applies whatever "purge" means to all of the > children and contents of the class, is what would need to happen... > I can see that being a huge can of worms though, I wonder what Luke > thinks.Yeah, purging is most likely the best and easiest solution, although you''ll always have the problem of what "absent" means for a given type, and this''ll never work for execs or files.> Currently my solution for this is to just automate the rebuild the > machine. Perhaps this is better (at least cleaner) in the long-run > anyway.Rebuilding is always cleaner, but it''s not exactly a smooth solution. -- A diplomat is a man who can convince his wife she''d look stout in a fur coat. --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com
2006/11/16, Luke Kanies <luke@madstop.com>:> > Blake Barnett wrote: > > > > I''ve been thinking about this exact scenario. I think a Purge at the > > class level, which applies whatever "purge" means to all of the > > children and contents of the class, is what would need to happen... > > I can see that being a huge can of worms though, I wonder what Luke > > thinks. > > Yeah, purging is most likely the best and easiest solution, although > you''ll always have the problem of what "absent" means for a given type, > and this''ll never work for execs or files. > > I think it would neither work for packages, in case you''re using a packagemanager that automatically handles dependencies: let''s say you install a given package, and the package manager installs all the dependencies; putting that package in the absent state (uninstalling it) would let you with all those dependencies still floating around. I think the idea of a class destructor (or similar) is not that bad. If puppet could know the current state of a node (list of classes) and the desired state it could first process all those class destructors for classes in the current state but not in the desired state. This would give us the opportunity of cleaning up after taking a node from a class. Unfortunately I don''t know enough about the puppet internals, so I don''t know if this is possible at all. Best regards Jose _______________________________________________ Puppet-users mailing list Puppet-users@madstop.com https://mail.madstop.com/mailman/listinfo/puppet-users
>> Currently my solution for this is to just automate the rebuild the >> machine. Perhaps this is better (at least cleaner) in the long-run >> anyway.>Rebuilding is always cleaner, but it''s not exactly a smooth solution.Agreed and for my hypothetical example of web -> mail server switching that''s the appropriate route no doubt. A more relevant example would be my case of switching the backup method of a host from rsync+ssh to Tivoli and perhaps back. I certainly don''t want to rebuild a machine for that.>I think the idea of a class destructor (or similar) is not that bad. If >puppet could know the current state of a node (list of classes) and the >desired state it could first process all those class destructors for >classes >in the current state but not in the desired state. This would give us >the >opportunity of cleaning up after taking a node from a class. >Unfortunately I >don''t know enough about the puppet internals, so I don''t know if this >is >possible at all.I like this mechanism a lot. This is probably what Luke and Blake mean by "purge" but I understand it better. Matt Collins
José González Gómez wrote:> I think it would neither work for packages, in case you''re using a > package manager that automatically handles dependencies: let''s say you > install a given package, and the package manager installs all the > dependencies; putting that package in the absent state (uninstalling it) > would let you with all those dependencies still floating around.I believe there are some packaging systems that can clean out this kind of abandoned packages, but I agree, in general it''s going to be a problem.> I think the idea of a class destructor (or similar) is not that bad. If > puppet could know the current state of a node (list of classes) and the > desired state it could first process all those class destructors for > classes in the current state but not in the desired state. This would > give us the opportunity of cleaning up after taking a node from a class. > Unfortunately I don''t know enough about the puppet internals, so I don''t > know if this is possible at all.Hmmm. This wouldn''t be all that difficult if storeconfigs were enabled, since that does have current state information. Any recommendations on syntax? Anyone interested in implementing this? I don''t know exactly how much work it is, but I''d expect it''s not all that much. -- If there is anything the nonconformist hates worse than a conformist, it''s another nonconformist who doesn''t conform to the prevailing standard of nonconformity. --Bill Vaughan --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com
Matt Collins wrote:> > I like this mechanism a lot. This is probably what Luke and Blake mean > by "purge" but I understand it better.Purging is simply removing any unmanaged objects of a given type. For instance, using your example of sshkey, if you enabled purging of sshkeys, then your clients would remove any keys that were installed locally but were not specified in their configurations. For instance, if you''ve got two classes, webserver and mailserver, and each of them install a key with the same name (i.e., webserver and mailserver). If you take a host out of the webserver class and enable purging of sshkey, the client will notice that the webserver key is still present but is not specified anywhere in the configuration, so it will mark the key for removal. Does that make sense? -- "In theory, there is no difference between theory and practice; In practice, there is." -- Chuck Reid --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com
(thought I sent this yesterday but I apparently managed not to) matt wrote:> I have a situation where I''d like to perform some actions when a node is > removed from a class. I have a few (homegrown) services that install ssh > keys in authorized_keys and it''s possible that a node may have the > service enabled and disabled during it''s lifetime. When disabled I''d > like to clean up the ssh keys for security reasons.There are two ways to look at this problem: Either you want to manage every ssh key, such that if you stop talking about a key it gets deleted, or you want some kind of state tracker that knows what used to be in your configuration but no longer is. I''m currently working on adding the first ability, which I''ve been alternately calling ''inclusive management'' or purging (that is, purging unmanaged resources). Assuming you were using the sshkey type, you would do this to purge unmanaged keys: type { sshkey: purge => true } Then, when you removed the class from a node, any associated keys would be purged. This was the major feature that delayed 0.20.1, but I failed to finish it. I think I''ve got it figured out finally, and I hope to have it out soon, but I''m traveling to London and then Bangalore and then Washington DC and then Palo Alto, so we''ll see how much I can get done on the plane. I''ve never made plans to have a state tracker that knew how to delete recently-unmanaged resources. It wouldn''t actually be that difficult to implement such a thing as an add-on to puppetd, but given my recent dalliances with the idea of hooking smaller tools into Puppet, it seems like it would make sense to have a separate tool that knew how to look at the state database and compare it to the last version. Frankly, this wouldn''t be all that difficult; keep a copy of the file around, read them both in, find any resources that are in the old file but not the new file, and remove them. Your only limitation at this point would be that every object would need a concept of "removal", which is not currently the case. I''ve been meaning to add a "reversal" parameter to ''exec'', but I haven''t gotten around to it, and there''s not clear equivalent to ''absent'' in services, for instance. It''d be very cool to have this tool, I think.> This brings up the broader question in my mind of what it means for a > node NOT to be in a class. I could see a scenario in the future where I > want to, for instance, change a web server to a mail server. If I change > "node myhost1 { include webserver }" to "node myhost1 { include > mailserver }" what should happen? And if I have another class > "ldapserver" in my configs that''s not listed under myhost1, should that > class guarantee that myhost1 doesn''t run ldap even though I never > assigned it to the node? Should I have classes like "not_webserver" and > wield them on a temporary basis when repurposing hosts? That seems > awfully imperative (boo!).Inverse classes would be insanely painful. I would consider it to be a heinous failure in Puppet if this were the best way to solve this problem. Are there some other ways of thinking about the problem? That is, if we step outside the language and just think about the process, are there ways we could create smaller tools for that process? [SNIP]> node mr_no_service { } > > node mr_service { include sshkey_service } > > > (The components are from the cookbook.) > > Unfortunately since nodes seem to be linked to classes last in the > parsing (from my reading of prior posts) the replace_line() is always > run. I''m open to alternate syntax suggestions. I saw a proposal about > the iptables config to set it up as a template and conditionally include > each line based on whether the node was tagged but I don''t like that as > it puts my config information in two places. I like keeping the key with > the service.It''s probably a pretty bad idea to depend on parse order to do anything like this. There are a couple of ways I can think of doing this, but I''d prefer to avoid them until we know if purging will/won''t work and have tried the client-side removal tools.> What might be cool are class destructors where if a class with a suffix > eg "_destructor" exists then every node that does not include the main > class has the destructor run. Something like: > > class a_file { > file { "/a_file": ensure => present } > } > > class a_file_destructor { > file { "/a_file": ensure => absent } > } > > node with_a_file { include a_file } > > node without_a_file { }Such a class should be automatically generatable assuming every contained resource has a clear "absent" concept, which isn''t always true. You''d run into problems if you had overlapping classes, though; e.g., if you had two webserver classes that managed some of the same elements but not all, and you changed from one class to the other, you''d be in big trouble with these destructor classes. I''d expect this to be a pretty common case for upgrades. -- Get with the program, jeffrey. No one is "wrong" on Usenet. They are either 100% totally correct, or they are "a lying, scum sucking weasel." There is no in between. -- Garrett Johnson, in talk.politics.misc --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com