3

Sometimes there are complicated interactions between packages. To avoid class interface with countless, seemingly unrelated parameters, I though about using tags, defined(<resource>) function to let the resources slightly change their behaviour based on the rest of the configuration (not facts).

Unfortunately I can't figure out a way to let the Puppet first parse the class that can generate conditions, and only then parse the class which behaviour implicitly (via e.g. tags) depends on the way the first class got executed.

Suppose here is a class, that manages a place, where a specific user stores his sensitive personal data. The class can e.g. create the partition (possibly encrypted), or just maintain an external folder (on e.g. /mnt/user). Or it can keep the folders where they are by default, i.e. in the /home/user (spurcetype=>'none')

class userdocs ( $sourcetype) {
  case $sourcetype {
    'cryptpartition' : {
      tag 'dedicated_user_docs_partition'
      ...
    }
    'partition' : {
      tag 'dedicated_user_docs_partition'
      ...
    }
    'none' : {
      ...
    }
  }
  ...
}

Apart from fairly standard set of folders, that a user might want to forward to his partition, there are folders which existence depends on the particular software running, like thunderbird or virtualbox. Creation of the link (instead of folder) for e.g. virtualbox should be done only, if two conditions are satisfied: a) user manages separate partition (tagged('dedicated_user_docs_partition')) and user installs VirtualBox.

There must be a place, where I can put that extra code, that checks for those two conditions. I can put it into the class, that manages the virtualbox:

class vbox {
  if tagged('dedicated_user_docs_partition') {
    file { "${userhome}/.VirtualBox": ensure=>link, require=>Class['userdocs'] ...
    }
  } else {
    file { "${userhome}/.VirtualBox": ensure=>directory, require=>Class['userdocs'] ...
    }
  }
  ...
}

The problem is, that although I explicitly require the file resource to be executed before the userdocs class, the file resource is evaluated after that, and puppet wrongly assumes, that user doesn't have the dedicated_user_docs_partition and executes wrong branch of the if statement.

Is there any way to solve this problem?


I've cross-posted this question on ask.puppetlabs.com.

  • 1
    Why not have custom facts for that? Also: Have you thought about putting the userdoc class into an earlier stage (docs.puppetlabs.com/puppet/latest/reference/…)? But I'd prefer the facts solution. – faker Apr 23 '14 at 11:24
  • And how do you declare vbox? Does class {'vbox': require => Class['userdoc'], } not work? – faker Apr 23 '14 at 11:48
  • @faker I don't understand, why you like them. Facts are instantiated only once, at the beginning. I would need to run a manifest twice (which is not elegant), and handle three states in place of two: "dedicated_docs", "no_dedicated_docs", "first_run". – Adam Ryczkowski Apr 23 '14 at 14:24
  • @faker ... Besides in real situation (not this mock-up example), both vbox and userdocs are in fact a define, not class, and they have user name as a namevar. I understand, that I would need to have as many facts as there are users, which would greatly proliferate the namespace. – Adam Ryczkowski Apr 23 '14 at 14:26
  • @facter Does class {'vbox': require => Class['userdoc'], } not work? - no it doesn't. Although I get the correct order of execution, but this doesn't affect the order in which classes are parsed. – Adam Ryczkowski Apr 23 '14 at 16:48
1

It is a an answer using virtual resources, that lavaman suggested.

I don't like the fact, that it forces me to put code with "VirtualBox" to the class, that I think should be logically independent to it. But I think it can be worked-around using delegated classes (like userdocs::virtualbox, defined completely elsewhere).

class userdocs ( $sourcetype) {
  case $sourcetype {
    'cryptpartition' : {
      @file { "${userhome}/.VirtualBox": ensure=>link, ...
      }
      ...
    }
    'partition' : {
      @file { "${userhome}/.VirtualBox": ensure=>link, ...
      }
      ...
    }
    'none' : {
      @file { "${userhome}/.VirtualBox": ensure=>directory, ...
      }
      ...
    }
  }
  ...
}

and

class vbox {
  realize File["${userhome}/.VirtualBox"]
  ...

}

0

For this answer credit goes to user lavaman on ask.puppetlabs.com:

Assuming you are managing the software with puppet as well (which appears to be the case from your sample code), I would use virtual resources in the software modules that get collected by the module handling the mounts.

http://docs.puppetlabs.com/puppet/latest/reference/lang_virtual.html

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.