Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am starting to setup puppet. I want to set up a dependencies that a mail transfer agent must be installed before that class tries to install or start anything. With puppet, the standard method seems to set a dependency seems to be require blah. The challenge is I don't use the same MTA on all of my systems. Some of the systems which are actual mail servers I have a full MTA (exim), but the vast majority of my systems have ssmtp installed. What I want do is setup a requirement so that either one of those MTAs is installed and functional before the the foo class is processed.

Here is a configuration that somewhat demonstrates what i am trying to do.

node default {
  if $fqdn in ["mail1.example.org", 
               "mail2.example.org", 
               "mail3.example.org"] {

    include fullmta  # mailhub, and so on
  } else {
    include ssmtp    # really basic send-only mta.
  }
  include foo        # class that requries an mta be installed
}

class foo {
  require MTA # FIXME, A valid mta is required.

  package { foo: ensure => present, }
  ... # also a service, and some files, and so on...
}

So in my foo class, how do I require that one of the possible MTAs classes has been processed?

share|improve this question

3 Answers 3

up vote 4 down vote accepted

If you split the MTA logic to a separate class, you can handle the logic there - and your resources can require the MTA class to enforce the dependency relationship.

node default {
  include mta
  include foo        # class that requries an mta be installed
}

class mta {
  if $fqdn in ["mail1.example.org", 
               "mail2.example.org", 
               "mail3.example.org"] {

    include fullmta  # mailhub, and so on
  } else {
    include ssmtp    # really basic send-only mta.
  }
}

class foo {
  package { foo: ensure => present,
                 require => Class['mta'], }
  ... # also a service, and some files, and so on...
}
share|improve this answer

Use an alias. Something like this:

service { "ssmtp":
    ...
    alias => "MTA",
}

service { "fullmta":
    ...
    alias => "MTA",
}

class foo {
    package { foo:
        ensure  => present,
        require => Service["mta"],
        ...
    }
    ...
}
share|improve this answer

You can specify require dependencies as arrays, in which case Puppet will make sure all dependencies are met before proceeding. In this situation I usually do something like the following:

node default {
  include mta
  include foo        # class that requries an mta be installed
}

class mta {
  if $fqdn in ["mail1.example.org", 
               "mail2.example.org", 
               "mail3.example.org"] {
    package { "conflicting-package-A": ensure => present, }
    package { "conflicting-package-B": ensure => absent, }
  } else {
    package { "conflicting-package-A": ensure => absent, }
    package { "conflicting-package-B": ensure => present, }
  }
} 

class foo {
  package { foo: ensure => present,
                 require => [Package["conflicting-package-A",
                                     "conflicting-package-B"], }
  ... # also a service, and some files, and so on...
}

This way, you not only make sure that the foo package is explicitly dependent on both other packages, but you set things up so that if you remove a host from the mail*.example.org list in the future, that "conflicting-package-A" will be replaced with "conflicting-package-B" automatically.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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