include resources from another class

38 views
Skip to first unread message

Tim Dunphy

unread,
Mar 6, 2014, 1:17:00 PM3/6/14
to puppet...@googlegroups.com
Hey all,

 I have a module that I've written called 'lumberjack'. It installs the logstash forwarding agent called 'lumberjack' and gets the service running. However it depends on ca certificate which I include in another class (called simply 'ca').

Yet if I try to include a resource from the 'ca' class I get the following failure: 

err: Failed to apply catalog: Could not find dependency File[/etc/pki/CA/certs/ca.crt] for Service[lumberjack] at /etc/puppet/environments/production/modules/lumberjack/manifests/service.pp:8

I really did think that if I included a class into another one like so:

class lumberjack::service {

  include ca

  service { lumberjack:
     ensure => running,
     require => File["/etc/pki/CA/certs/ca.crt"],
  }


}

I'd be able to refer to the resource from the other class. I think we had a debate about the rightness or wrongness of including material from other classes in our resources. So I'm just wondering what the best way of going about what I'm trying to achieve might be.

The goal here will be to install the lumberjack log shipping agent and get the service running in one fell swoop. If I remove the cert requirement (require => File["/etc/pki/CA/certs/ca.crt"],)  the puppet run will error out initially when it tries to run the service and can't find the ca.crt file. The second run will generally be ok.

Thanks
Tim

--
GPG me!!

gpg --keyserver pool.sks-keyservers.net --recv-keys F186197B

Garrett Honeycutt

unread,
Mar 6, 2014, 1:42:25 PM3/6/14
to puppet...@googlegroups.com


Hi,

You could change 'include ca' to 'require ca' and then safely remove the require attribute from the service resource. This would ensure that all of the resources from the ca class are handled before your service class.

Best regards,
-g

--
Garrett Honeycutt
LearnPuppet.com
@learnpuppet

jcbollinger

unread,
Mar 7, 2014, 9:19:42 AM3/7/14
to puppet...@googlegroups.com


On Thursday, March 6, 2014 12:42:25 PM UTC-6, Garrett Honeycutt wrote:

You could change 'include ca' to 'require ca' and then safely remove the require attribute from the service resource. This would ensure that all of the resources from the ca class are handled before your service class.


Yes, but no.  The problem is not a resource ordering issue, it is a resource declaration issue.  It cannot be resolved by adding resource relationships (unless incidentally), because Puppet disagrees with the OP that the resource in question has been declared at all.  If it were in fact declared in class 'ca' then the error would not occur.

It is possible that there is a difference in the spelling of the file name between class 'ca' and class 'lumberjack::service'.  In that case, switching from a relationship with the File to one with the Class would make the error go away (c.f. "incidentally"), but it would not ensure that a file of the name previously specified in class 'lumberjack::service' was managed.


John

jcbollinger

unread,
Mar 7, 2014, 9:37:52 AM3/7/14
to puppet...@googlegroups.com


On Thursday, March 6, 2014 12:17:00 PM UTC-6, bluethundr wrote:
Hey all,

 I have a module that I've written called 'lumberjack'. It installs the logstash forwarding agent called 'lumberjack' and gets the service running. However it depends on ca certificate which I include in another class (called simply 'ca').

Yet if I try to include a resource from the 'ca' class I get the following failure: 

err: Failed to apply catalog: Could not find dependency File[/etc/pki/CA/certs/ca.crt] for Service[lumberjack] at /etc/puppet/environments/production/modules/lumberjack/manifests/service.pp:8



Puppet disagrees with you.  It is telling you that no File resource of that name has been declared anywhere among all the declarations contributing to the target node's catalog.  Check your spelling.  Check also that you're getting the right 'ca' class -- it would be best to use its fully-qualified name.
 
I really did think that if I included a class into another one like so:

class lumberjack::service {

  include ca

  service { lumberjack:
     ensure => running,
     require => File["/etc/pki/CA/certs/ca.crt"],
  }


}

I'd be able to refer to the resource from the other class. I think we had a debate about the rightness or wrongness of including material from other classes in our resources. So I'm just wondering what the best way of going about what I'm trying to achieve might be.



Be very careful: your wording suggests a misunderstanding of the meaning of an 'include' statement.  In Puppet, an 'include' does not perform textual interpolation ala the 'include' and similar statements of various programming languages and preprocessors.  It does not include another class in the one where the statement appears; rather, it includes the specified class in the target node's catalog.  That is one form of "declaring" the specified class.

Having declared the class, however, you can be confident that all resources declared directly or indirectly by it will be in the catalog and therefore (among other things) available as relationship targets.  That's why I say Puppet disagrees with you about the File being declared by class 'ca' (as that class name is resolved relative to 'lumberjack::service').

 
The goal here will be to install the lumberjack log shipping agent and get the service running in one fell swoop. If I remove the cert requirement (require => File["/etc/pki/CA/certs/ca.crt"],)  the puppet run will error out initially when it tries to run the service and can't find the ca.crt file. The second run will generally be ok.



That is indeed the hallmark of a resource ordering problem, for which declaring one or more appropriate relationships is the appropriate solution.  There is some debate in the community over whether it is ever a good practice to declare relationships with resource declared by other classes.  The prevailing opinion here seems to be "no", but I personally have a more nuanced view.  There wouldn't even be a debate, however, if it didn't work.

If you subscribe to the view that classes should not declare relationships directly with resources declared by other classes, then alternative is, roughly, to target the relationship on the declaring class.  That is more or less what Garrett is suggesting, but do pay attention to my response to his comments (much of which is reflected also above).


John

Reply all
Reply to author
Forward
0 new messages