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.puppet.com.

5
  • 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, 2014 at 11:24
  • And how do you declare vbox? Does class {'vbox': require => Class['userdoc'], } not work?
    – faker
    Apr 23, 2014 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". Apr 23, 2014 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. Apr 23, 2014 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. Apr 23, 2014 at 16:48

2 Answers 2

2

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.

Official documentation: https://puppet.com/docs/puppet/latest/lang_virtual.html

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .