"require" broken with create_resources() ?

883 views
Skip to first unread message

Vincent Miszczak

unread,
Aug 20, 2014, 7:04:56 AM8/20/14
to puppet...@googlegroups.com
Hello,

I have a define like this :

define application::install($root,$url,$user="root")
{
 include git
 
#Puppet wants a command to start with /something...
 $cmd
="/bin/echo 1&&{ cd $root||mkdir $root&&cd $root ; }&&git clone -b prod $url ."
 $unless
="/bin/ls -alh $root |grep '.git'"


 
exec{"$cmd":
 command
=>$cmd,
 
unless=>$unless,
 user
=>$user,
 
require=>Package["git"]
 
}
}


being called with a class :

class applications($apps)
{
  create_resources
(application::install,$apps)
}


and 
$apps = {
   test
=> {
     url
=> "https://mygitrepos/myapp.git",
     root
=> "/opt/apps/myapp",
     user
=>"root",
     
require=>Class[myclass],
   
}
}


class "myclass" is included by some other module

I get :

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Invalid relationship: Application::Install[test] { require => Class[myclass] }, because Class[myclass] doesn't seem to be in the catalog

but the class is really included.

For instance, if I do not require in $apps but require in the exec{}, it will work just fine. Ofc I won't do this because I need things to be dynamic.

Expected behavior is it should work, unless I missed something.

Any help welcome.





jcbollinger

unread,
Aug 20, 2014, 9:01:09 AM8/20/14
to puppet...@googlegroups.com


I'm a bit surprised to hear that doesn't work when the hash passed to create_resources() is initialized via a literal, as you show.  If that's how you plan to do it, though, then you could instead establish the relationship separately by use of the chain operator:

    Class['myclass'] -> Application::Install['test']

That's not really what I'd call "dynamic", however, so I suspect what you're really trying to do is express that hash in hiera data.  Indeed that won't work, at least not with the default back-end (YAML), because YAML has no mechanism for expressing Puppet resource references.  The value "Class[myclass]" is just a string in YAML.  You could work around such a problem by expressing required class names in your data rather than class references (and then applying the chain operator appropriately in your defined type).


John

R.I.Pienaar

unread,
Aug 20, 2014, 9:11:13 AM8/20/14
to puppet...@googlegroups.com
> > but the class *is* really included.
> >
> > For instance, if I do not require in $apps but require in the exec{}, it
> > will work just fine. Ofc I won't do this because I need things to be
> > dynamic.
> >
> > Expected behavior is it should work, unless I missed something.
> >
> > Any help welcome.
> >
> >
>
> I'm a bit surprised to hear that doesn't work when the hash passed to
> create_resources() is initialized via a literal, as you show. If that's
> how you plan to do it, though, then you could instead establish the
> relationship separately by use of the chain operator:
>
> Class['myclass'] -> Application::Install['test']
>
> That's not really what I'd call "dynamic", however, so I suspect what
> you're really trying to do is express that hash in hiera data. Indeed that
> *won't* work, at least not with the default back-end (YAML), because YAML
> has no mechanism for expressing Puppet resource references. The value
> "Class[myclass]" is just a string in YAML. You could work around such a
> problem by expressing required class names in your data rather than class
> references (and then applying the chain operator appropriately in your
> defined type).


It seems to work fine for me, the code below does what you'd expect:

class myclass {
notify{"woop": }
}

include myclass

$resources = {"/usr/bin/cowsay 'it works fine'" => {"logoutput" => "true", "require" => Class[myclass]}}

create_resources("exec", $resources)

It also works if you quote the 'Class[myclass]' so it should work if it comes from JSON or whatever

Vincent Miszczak

unread,
Aug 20, 2014, 9:50:22 AM8/20/14
to puppet...@googlegroups.com
I've simplified things a bit in the description to make it easy to read.

I don't really have 
$apps = { 
   test 
=> {
     url
=> "https://mygitrepos/myapp.git",
     root
=> "/opt/apps/myapp",
     user
=>"root",
     
require=>Class[myclass],
   
}
}


Instead, I pass a YAML hash through an ENC (Foreman to be precise):
test:
 url
: "https://mygitrepos/myapp.git"
 root
:"/opt/apps/myapp"
 user
: root
 
require: Class[myclass]


I finally understand this won't work because this is expanded to require=>"Class[myclass]" instead of require=>Class[myclass].
I was mislead by the error message that does not have any quote to distinguish strings from the rest.

As suggested in the previous post doing :
requirement: myclass

and having into 
define application::install($root,$url,$user="root",$requirement=undef)

exec{"$cmd":
 command
=>$cmd,
 
unless=>$unless,
 user
=>$user,

 
require=>[Package["git"],Class[$requirement]]
 
}

This is not as powerful as what I intended first (because I'm restricted to class, not all types I want), but for now, this is enough for my precise problem.

Thank you very much guys! 

Joseph Swick

unread,
Aug 20, 2014, 10:46:18 AM8/20/14
to puppet...@googlegroups.com
On 20/08/14 09:50, Vincent Miszczak wrote:
<trim>
>
> Instead, I pass a YAML hash through an ENC (Foreman to be precise):
> test:
> url: "https://mygitrepos/myapp.git"
> root:"/opt/apps/myapp"
> user: root
> require: Class[myclass]
>
>
> I finally understand this won't work because this is expanded to
> require=>"Class[myclass]" instead of require=>Class[myclass].
> I was mislead by the error message that does not have any quote to
> distinguish strings from the rest.
>

I wonder if this is a limitation of Foreman or how Foreman is passing
the hash to Puppet? As I'm doing something similar to this in yaml with
hiera:

classes:
- basic::directory
- myservice
basic::directory::instance:
'/data/myservice/':
owner: svc_account
group: svc_account
mode: '0755'
require: Package[myservice]
before: Service[myservice]
myservice::data_dir: /data/myservice

The basic::directory class is a simple wrapper around create_resources
for the file resource.

class basic::directory ($instance){
$real_instance = hiera_hash(basic::directory::instance)
$defaults = {
'ensure' => 'directory',
'mode' => '0755',
'owner' => 'root',
'group' => 'root',
}
create_resources(file, $real_instance, $defaults)
}

The 'myservice' class handles the installation and management of the
service. In it the package is an RPM that creates the user account for
the service to run under, so the account doesn't exist until the package
is installed. However, the directory needs to be created with the
correct ownership and permissions before the service is started, as it's
been configured not to use the default directory.

This worked as desired when I first did it and I haven't seen any
errors. However, from reading the other comments in the thread, maybe
it shouldn't work?

--
Joseph Swick <joseph...@meltwater.com>
Operations Engineer
Meltwater Group

signature.asc

jcbollinger

unread,
Aug 21, 2014, 9:00:28 AM8/21/14
to puppet...@googlegroups.com


On Wednesday, August 20, 2014 8:11:13 AM UTC-5, R.I. Pienaar wrote:

It also works if you quote the 'Class[myclass]' so it should work if it comes from JSON or whatever


Really?  That's news to me.  I wonder when that was added.


John

Vincent Miszczak

unread,
Aug 21, 2014, 2:19:07 PM8/21/14
to puppet...@googlegroups.com
I've done some tests :

Foreman really just reply a YAML hash with the class name and its parameters (there is a viewer, it just output what it should).

I've been trying parse order issue ("myclass" is output after "applications"), but having "anotherclass" that come before, it does not work.
I've been trying type issue, by refering something else than a class, still does not work.

It looks like there is a difference in this case between the ENC subsystem and Hiera :/



Ramin K

unread,
Aug 21, 2014, 2:21:51 PM8/21/14
to puppet...@googlegroups.com
I'm curious as well. I distinctly remember losing an afternoon to the
fact that this did not work last year. hiera-1.3 maybe?

Ramin

R.I.Pienaar

unread,
Aug 21, 2014, 2:28:03 PM8/21/14
to puppet...@googlegroups.com
show the yaml
Reply all
Reply to author
Forward
0 new messages