Writing a non-ensurable type/provider

21 views
Skip to first unread message

Dirk Heinrichs

unread,
Feb 25, 2019, 2:47:34 AM2/25/19
to puppet...@googlegroups.com
Hi,

I need to write a custom type to configure a third party tool through REST API calls. This means I have to:

  1. Get the configuration via REST call and provide it as hash
  2. Modify the requested attributes
  3. Upload the modified configuration and request the the tool to restart itself (both via REST API).

This doesn't sound like a classical ensurable type to me. However, I've got some difficulties to understand how to write a type that isn't ensurable and how such a type would interact with its provider (in case I need one at all), so that it's still idempotent. The resource call should then look like this:

myconfig { 'somename':
option1 => 'value1',
option2 => 'value2',
...,
require => [Something],
}

Could someone please point me into the right direction?

Thanks a lot...

Dirk
-- 
Dirk Heinrichs
Senior Systems Engineer, Delivery Pipeline
OpenText ™ Discovery | Recommind
Recommind GmbH, Von-Liebig-Straße 1, 53359 Rheinbach
Vertretungsberechtigte Geschäftsführer John Marshall Doolittle, Gordon Davies, Christian Waida, Registergericht Amtsgericht Bonn, Registernummer HRB 10646
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail sind nicht gestattet.

Martin Alfke

unread,
Feb 25, 2019, 3:10:39 AM2/25/19
to puppet...@googlegroups.com
Hi,

> On 25. Feb 2019, at 08:47, Dirk Heinrichs <dhei...@opentext.com> wrote:
>
> Hi,
>
> I need to write a custom type to configure a third party tool through REST API calls. This means I have to:
>
> • Get the configuration via REST call and provide it as hash
> • Modify the requested attributes
> • Upload the modified configuration and request the the tool to restart itself (both via REST API).
>
I assume that there are some types/provider who exactly do this. I just have no example at hand.

> This doesn't sound like a classical ensurable type to me. However, I've got some difficulties to understand how to write a type that isn't ensurable and how such a type would interact with its provider (in case I need one at all), so that it's still idempotent. The resource call should then look like this:

The type describes the resource parameters and its data validation. Additionally one can add autorequires to other resource types.
Whether a type is ensurable or not has no impact on the provider. Within a type it is just the ensurable declaration.
When a type is ensurable you wi have destroy and create methods in the provider.

Within the provider you specify getters (how to read existing data) and setters (how to set new data).
Maybe you want to have a look at my PuppetConf talk "Moving from exec to types and providers". You can find it at Puppet youtube channel.
There I describe getters and setters.

hth,
Martin

>
> myconfig { 'somename':
> option1 => 'value1',
> option2 => 'value2',
> ...,
> require => [Something],
> }
>
> Could someone please point me into the right direction?
>
> Thanks a lot...
>
> Dirk
> --
> Dirk Heinrichs
> Senior Systems Engineer, Delivery Pipeline
> OpenText ™ Discovery | Recommind
> Phone: +49 2226 15966 18
> Email: dhei...@opentext.com
> Website: www.recommind.de
> Recommind GmbH, Von-Liebig-Straße 1, 53359 Rheinbach
> Vertretungsberechtigte Geschäftsführer John Marshall Doolittle, Gordon Davies, Christian Waida, Registergericht Amtsgericht Bonn, Registernummer HRB 10646
> This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden
> Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail sind nicht gestattet.
>
> --
> 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/192ca5b4da8bda73365493c34a48dc85d2c7a2d9.camel%40opentext.com.
> For more options, visit https://groups.google.com/d/optout.

Dirk Heinrichs

unread,
Feb 25, 2019, 3:30:02 AM2/25/19
to puppet...@googlegroups.com
Am Montag, den 25.02.2019, 09:10 +0100 schrieb Martin Alfke:

Within the provider you specify getters (how to read existing data) and setters (how to set new data).
Maybe you want to have a look at my PuppetConf talk "Moving from exec to types and providers". You can find it at Puppet youtube channel.
There I describe getters and setters.

Thanks a lot. I think I've already understood that part. The problem I have is how to implement points 1 and 3 (getting the current configuration and writing back the changes). What are the entry points for these? If a type is ensurable I have "exists?", "create" and "destroy", but what do I use if it's not?

Bye...

Martin Alfke

unread,
Feb 25, 2019, 3:41:13 AM2/25/19
to puppet...@googlegroups.com


> On 25. Feb 2019, at 09:29, Dirk Heinrichs <dhei...@opentext.com> wrote:
>
> Am Montag, den 25.02.2019, 09:10 +0100 schrieb Martin Alfke:
>
>> Within the provider you specify getters (how to read existing data) and setters (how to set new data).
>> Maybe you want to have a look at my PuppetConf talk "Moving from exec to types and providers". You can find it at Puppet youtube channel.
>> There I describe getters and setters.
>
> Thanks a lot. I think I've already understood that part. The problem I have is how to implement points 1 and 3 (getting the current configuration and writing back the changes). What are the entry points for these? If a type is ensurable I have "exists?", "create" and "destroy", but what do I use if it's not?

Well, when it is not ensurable then Puppet expects that a configuration artefact is always present.
You then just have the getter and setter for the type parameters and maybe some helper methods (API calls, data transformation).

example:

mytype { 'title':
config1 => 'data',
config2 => 'data',
}

provider:

def config1
# write code to read data
end

def config1=(value)
# code to set/write data
end

>
> Bye...
>
> Dirk
> --
> Dirk Heinrichs
> Senior Systems Engineer, Delivery Pipeline
> OpenText ™ Discovery | Recommind
> Phone: +49 2226 15966 18
> Email: dhei...@opentext.com
> Website: www.recommind.de
> Recommind GmbH, Von-Liebig-Straße 1, 53359 Rheinbach
> Vertretungsberechtigte Geschäftsführer John Marshall Doolittle, Gordon Davies, Christian Waida, Registergericht Amtsgericht Bonn, Registernummer HRB 10646
> This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden
> Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail sind nicht gestattet.
>
> --
> 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/3145d6ea8e2c3a64dcf475c8d5c6f33a471f719d.camel%40opentext.com.

David Schmitt

unread,
Feb 25, 2019, 7:29:23 AM2/25/19
to puppet...@googlegroups.com
Hi Dirk,

this is possible using the Resource API, and instead of using the `set` method implemented in SimpleProvider (which is the default if you do `pdk new provider`) create your own simpler version.

The Resource API is part of puppet 6, and available as side-loadable gem for previous versions. There is a puppet module to install it.


Regards, David

--
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.

For more options, visit https://groups.google.com/d/optout.
--

jcbollinger

unread,
Feb 25, 2019, 9:26:06 AM2/25/19
to Puppet Users


On Monday, February 25, 2019 at 2:30:02 AM UTC-6, Dirk Heinrichs wrote:
Am Montag, den 25.02.2019, 09:10 +0100 schrieb Martin Alfke:

Within the provider you specify getters (how to read existing data) and setters (how to set new data).
Maybe you want to have a look at my PuppetConf talk "Moving from exec to types and providers". You can find it at Puppet youtube channel.
There I describe getters and setters.

Thanks a lot. I think I've already understood that part. The problem I have is how to implement points 1 and 3 (getting the current configuration and writing back the changes). What are the entry points for these? If a type is ensurable I have "exists?", "create" and "destroy", but what do I use if it's not?


If the complete set of instances is well known, or if the API provides a way to enumerate instances, then your provider should be able to implement prefetching.  It can in any case implement flushing.  These can serve as the entry points you're looking for.  If you can't or don't want to use one or both of these, then the alternative entry points are the property getter and setter methods, respectively.

It sounds like your API deals with state in whole-object units.  That's a classic case for implementing flushing.  It plays well with prefetching, too, but if you cannot enumerate instances or otherwise don't want to prefetch, then your provider can still implement its own, custom support for as-needed state fetching, and it can make all the property getters hook that.  For example, you could have methods is_fetched?() and fetch(),  and begin each property (not parameter) getter with

  fetch unless is_fetched?

Do understand that these method names are not special.  Puppet offers no built-in hooks for these particular operations.

You can implement something analogous on the setter side, but unless you have a way to modify properties individually, I don't see a reason to prefer that over flushing.


John

Dirk Heinrichs

unread,
Feb 26, 2019, 1:33:23 AM2/26/19
to puppet...@googlegroups.com
Thanks a lot. I followed Martin's talk he mentioned in his first reply and through that I got to Tim Cinel's slides. I could use his Bamboo types and providers as a starting point.
Reply all
Reply to author
Forward
0 new messages