Tom17
Tom17

Reputation: 426

Deleting configuration items with chef

I am relatively new to Chef and and doing a proof-of-concept by trying to use it to build a web server. For reasons out-of-scope to this question, I will be creating multiple Apache instances that I may want to both create and "delete". The same question could really apply to creating and deleting virtual host configurations within a single Apache instance.

I am currently using chef-client to create all my Apache instances based on defined attributes for this node. So for example, I may have attributes defining Instance1, Instance2 and Instance3. This is all working just fine at this point. Instance directories get created as so:

/opt/local/apache/Instance1/stuff
/opt/local/apache/Instance2/stuff 
/opt/local/apache/Instance3/stuff

Content directories and services get created with the same instancename identifier.

The problem comes if I were to, say, remove Instance3 from the attributes for this node. My chef-client run will ensure that Instance1 & Instance2 are configured correctly, but Instance3 will remain as chef-client now knows nothing about it.

I understand that in an ideal world, you may just spin up a new machine with the new configuration and this problem does not even raise its head. However, I need to do this on a server that cannot be re-provisioned (This is just a POC for configuring Apache on an existing server).

I could just "delete and recreate", but this does not sound idempotent to me. For one, the file timestamps would differ. It also seems wrong to have chef-client do all that stuff even if there is nothing to do.

I have come up with a solution myself. In the example above I would, in Ruby, get a list of all instance names by globbing /opt/local/apache/, iterating them and deleting the instance if it's not an instance that was defined in the attributes. I put this into a separate recipe that I called cleanup.rb. If I run this after the main install recipe and if there have been no removed configurations, then it would do nothing so seems safe to run.

This works well, but it seems hacky and I worry that this may be an anti-pattern. Conceptually, am I going about this the right way or should I be doing something different? Is it considered normal and correct to have custom Ruby code in your recipes to do stuff like this?

Upvotes: 1

Views: 247

Answers (1)

coderanger
coderanger

Reputation: 54181

The distinction here is usually phrased (using the terms from Facebook's Phil D) as "managed objects" vs. "managed collection". A single template resource convergently controls the state of a file, but what you want is a resource (either an actual custom resource or just conceptually) that is the collection of all the files. You can check out the zap cookbook for a semi-reusable implementation of this, though that one is based around mining the resource collection rather than using attributes. Attribute-based collection approaches are a lot less fragile than the zap cookbook, but also more limited. Facebook's approach (i.e. attribute based) is probably best exemplified in their sysctl cookbook, https://github.com/facebook/chef-cookbooks/tree/master/cookbooks/fb_sysctl.

In this case it sounds like doing a dir glob and diff-ing that against the attribute data is probably the right way to go but just understand this can be "tricky" sometimes. Like if you set attributes in recipe code that happens after that glob, it wouldn't know about it. This usually leads to escalating special cases, but maybe you can keep things more orderly and it will be okay :)

Upvotes: 2

Related Questions