Ask Your Question
1

How to conditionally import a class

asked 2014-07-28 13:33:31 -0500

spuder gravatar image

How would you conditionally include a class and set an order?

ls
init.pp
RedHat.pp
Debain.pp
Jenkins.pp


cat init.pp
class foo ( $jenkins_slave=false ) {
  case ${::osfamily} {
    'RedHat': { include foo::RedHat } 
    'Debian': { include foo::Debian }
  }

  if $jenkins_slave == true {
    include foo::jenkins
  }
}

cat jenkins.pp
class foo::jenkins inherits foo {

  package { 'some-package':
    ensure => present,
    source => "http://some-private-repo-defined-in-redhat.pp"
  }
}

The problem is that Jenkins.pp is included before Redhat.pp / Debian.pp. The latter two classes set up the appropriate repos that are required by jenkins.pp

I don't see any way to make jenkins.pp run after the redhat/debian classes without a whole bunch of if else statements.

Options that I see:

Move the entire jenkins.pp inside redhat and debian.pp. The downside to this is there will be a lot of code duplication. Aslo jenkins.pp is relativly large

or

Put a require on the 'some-package' resource.

  package { 'some-package':
    ensure => present,
    source => "http://some-private-repo-defined-in-redhat.pp"
   require => Class["foo::${osfamily}]
  }

The downside to this is that putting dependencies inside classes is frown upon.

or

Use the anchor pattern. Unfortunately this also will require a collection of if else statements, and variables for class names

Are there any alternatives? If not, what would be the best way to approach this problem?

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
0

answered 2014-07-28 15:01:29 -0500

ramindk gravatar image

If you must have classes named after the OS, which isn't my favorite way to deal with this, you can do the following. Also don't capitalize the classes unless you're referring to the namespace in the DSL.

class foo ( $jenkins_slave=false ) {

  include foo::$osfamily # you might need to quote osfamily in someway, I forget.

  if $jenkins_slave == true {
    include foo::jenkins
    Class ["foo::${osfamily}"] -> Class['foo::jenkins'] # same thing with the quoting
  }
}

That said I'd put it all into Hiera where the logic belongs.

node some node {
   include profile::$osfamily
}

and then

class profile::debian {
  include ::apt

  # use hiera_hash and count on merging as well.
  $mypins = hiera_hash('apt::pins', {})
  create_resources('apt::pin', $mypins)
  $myrepos = hiera_hash('apt::repos', {})
  create_resources('apt::repo', $myrepos)
  # etc etc
}
edit flag offensive delete link more

Comments

Thanks, this is pretty much what I ended up doing. Since this is a masterless puppet module, I'm not sure I can use hiera.

spuder gravatar imagespuder ( 2014-07-29 09:44:40 -0500 )edit

Hiera works fine with masterless, but you'll need to push the data to the nodes when you sync code.

ramindk gravatar imageramindk ( 2014-07-30 13:00:32 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2014-07-28 13:33:31 -0500

Seen: 3,208 times

Last updated: Jul 28 '14