Implement custom resource parent/child relationship

33 views
Skip to first unread message

Quaternaire

unread,
Jan 12, 2016, 12:22:35 PM1/12/16
to Puppet Users
Hi,

I am creating a Module for Mantis Bug Tracker (an issue tracker, https://www.mantisbt.org/), and I need to create new resource types for Project and User.

The idea is to have Projects which can inherit from other Projects. Each Project can have multiple parent and/or childs, such as:

Project A
> Project B
>> Project Z
> Project C
>> Project Z



Where B an C are child of A, and Z is child of both B and C.
Also, project inheritance is parameterized (such a whether a child inherit parent properties).

I have no issue implementing the types and providers themselves, it is more with the end-user usage. Lets say I want to write a manifest representing the example above. The first soluton that comes in mind could be:

project { 'A':
 
ensure => present,
}

project
{ 'B':
 
ensure   => present,
  parent  
=> 'A',
  inherit  
=> true,
}

project
{ 'C':
 
ensure   => present,
  parent  
=> 'A',
  inherit  
=> false,
}

project
{ 'Z':
 
ensure   => present,
  parent  
=> 'B',
  inherit  
=> false,
}
# Crap, how can Z have multiple parents?
# Same problem if we use something like "child => 'B'" on A, how could A have multiple children?


... which is not viable.

Another solution could be:
project { 'A':
 
ensure => present,
}

project
{ 'B':
 
ensure   => present,
}

project
{ 'C':
 
ensure   => present,
}

hierarchy
{ 'A>B':
  child    
=> 'B',
  parent    
=> 'A',
  inherit  
=> true,
}

hierarchy
{ 'B>Z':
  child    
=> 'Z',
  parent    
=> 'B',
  inherit  
=> false,
}

hierarchy
{ 'C>Z':
  child    
=> 'Z',
  parent    
=> 'C',
  inherit  
=> true,
}



This way it works fine, but it is quite cumbersome to write and maintain.

So another way would be using hashes to define children (of parents):

project
{ 'A':
 
ensure => present,
  child  
=> {
    name    
=> 'B',
    inherit  
=> true,
 
}
}

project
{ 'B':
 
ensure   => present,
  child    
=> {
    name      
=> 'Z',
    inherit    
=> false,
 
} # We may add more child in this hash...
}

project
{ 'C':
 
ensure   => present,
  child    
=> {
    name      
=> 'Z',
    inherit    
=> true,
 
} # We may add more child in this hash...
}



Which also works fine, is easier to read, but does it respects Puppet conventions? Users will be able to define whatever they want in these hashes, and the Puppet mechanism of param/property linked to methods would be broken.

What do you think would be the best possibility? Having a Project type and using a Hierarchy type to link it together, granting the possibility to use hashes, or another solution?

A final note: a similar problem is posed for users. How can we define a user resource, and manage user specific parameters for each projects? I think answering for projects will solve it for users.

Thanks by advance for your ideas or advices!

Peter Kristolaitis

unread,
Jan 12, 2016, 12:37:55 PM1/12/16
to puppet...@googlegroups.com
Why not just use arrays for the parent attribute?

project { 'Z':
 
ensure   => present,

  parent  
=> [ 'B', 'C' ],
  inherit  
=> false,
}
--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/c0de16c7-4e56-4dae-a123-058651acc22e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Quaternaire

unread,
Jan 13, 2016, 3:08:52 AM1/13/16
to Puppet Users
This way it's not possible to have inherit B => true, and inherit C => false. It's none or all, where we should be able to choose inheritance per project.

jcbollinger

unread,
Jan 13, 2016, 9:53:32 AM1/13/16
to Puppet Users


On Wednesday, January 13, 2016 at 2:08:52 AM UTC-6, Quaternaire wrote:
This way it's not possible to have inherit B => true, and inherit C => false. It's none or all, where we should be able to choose inheritance per project.

On Tuesday, January 12, 2016 at 6:37:55 PM UTC+1, Peter Kristolaitis wrote:
Why not just use arrays for the parent attribute?

project { 'Z':
 
ensure   => present,
  parent  
=> [ 'B', 'C' ],
  inherit  
=> false,
}



It's not entirely clear to me why you want to manage the contents of a Mantis database as system *configuration*, but Puppet is flexible enough to do it.

Your problem springs largely from the fact that your parent / child relationships have more state than just their presence or absence.  You need a way to convey that state.  You already know that you can do it via separate resources.  If you want to do it all within the Project resource, then you'll need to use one or more attributes with complex data type.  There are all manner of specific ways you could go here, including the one you proposed, but I would advise you to have children declare who their parents are, instead of having parents declare who their children are.  For example, you might support a form like this:

project { 'C':
 
ensure => present,

  parent
=> { 'A' => { 'inherit' => true }, 'B' => { 'inherit' => false } }
}


As for validating the contents of the hash-valued attributes, that's just par for the course.  With more complex data comes more complex requirements for validation.  Use the validation hook in your custom type to engage whatever validation is appropriate.


John

Quaternaire

unread,
Jan 13, 2016, 11:39:59 AM1/13/16
to Puppet Users

It's not entirely clear to me why you want to manage the contents of a Mantis database as system *configuration*, but Puppet is flexible enough to do it.

Managing database content this way seems in Puppet range (such as with macauthorization).
We also need MantisBT to be ready with pre-defined projects and users as some external components may have to generate issues, it thus become part of our environment configuration requirements.

Your problem springs largely from the fact that your parent / child relationships have more state than just their presence or absence.  You need a way to convey that state.  You already know that you can do it via separate resources.  If you want to do it all within the Project resource, then you'll need to use one or more attributes with complex data type.  There are all manner of specific ways you could go here, including the one you proposed, but I would advise you to have children declare who their parents are, instead of having parents declare who their children are.  For example, you might support a form like this:

project { 'C':
 
ensure => present,
  parent
=> { 'A' => { 'inherit' => true }, 'B' => { 'inherit' => false } }
}


As for validating the contents of the hash-valued attributes, that's just par for the course.  With more complex data comes more complex requirements for validation.  Use the validation hook in your custom type to engage whatever validation is appropriate.

Your explanation is quite clear, I'll probably use something like this. Thanks!
 
Reply all
Reply to author
Forward
0 new messages