From 3cdf450bbc3cfe7b464cd922f7e1a60dccdc4ae3 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 24 May 2019 14:03:41 +0100 Subject: [PATCH 01/11] (maint) typos and phrasing --- language/resource-api/README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 625ec5c..1c65569 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -69,7 +69,7 @@ The `Puppet::ResourceApi.register_type(options)` function takes the following ke * `autorequire`, `autobefore`, `autosubscribe`, and `autonotify`: a hash mapping resource types to titles. The titles must either be constants, or, if the value starts with a dollar sign, a reference to the value of an attribute. If the specified resources exist in the catalog, Puppet will create the relationsships requested here. * `features`: a list of API feature names, specifying which optional parts of this spec the provider supports. Currently defined features: `canonicalize`, `simple_get_filter`, and `supports_noop`. See below for details. -For autoloading work, this code needs to go into `lib/puppet/type/.rb` in your module. +For autoloading to work, this code needs to go into `lib/puppet/type/.rb` in your module. ### Composite Namevars ("title_patterns") @@ -77,7 +77,6 @@ Each resource being managed must be identified by a unique title. Usually this i If multiple attributes are defined with the `namevar` behaviour, the type SHOULD specify `title_patterns` that will tell Resource API how to get at the attributes from the title. If `title_patterns` is not specified a default pattern is applied, and matches against the first declared `namevar`. - > Note: The order of title_patterns is important. You should declare the most specific pattern first and end with the most generic. Each title pattern contains the: @@ -184,7 +183,7 @@ A missing `:should` entry indicates that a resource should be removed from the s The `set` method should always return `nil`. Any progress signaling should be done through the logging utilities described below. If the `set` method throws an exception, all resources that should change in this call and haven't already been marked with a definite state, will be marked as failed. The runtime will only call the `set` method if there are changes to be made, especially in the case of resources marked with `noop => true` (either locally or through a global flag). The runtime will not pass them to `set`. See `supports_noop` below for changing this behaviour if required. -Both methods take a `context` parameter which provides utilties from the runtime environment, and is decribed in more detail there. +Both methods take a `context` parameter which provides utilities from the runtime environment, and is described in more detail in its own section below. ## Implementing simple providers @@ -208,17 +207,17 @@ class Puppet::Provider::AptKey::AptKey < Puppet::ResourceApi::SimpleProvider Once all of that is in place, instead of the `set` method, the provider needs to implement the `create`, `update` or `delete` methods: * `create(context, name, should)`: This is called when a new resource should be created. - * `context`: provides utilties from the runtime environment, and is decribed in more detail there. + * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. * `name`: the name or hash of the new resource. * `should`: a hash of the attributes for the new instance. * `update(context, name, should)`: This is called when a resource should be updated. - * `context`: provides utilties from the runtime environment, and is decribed in more detail there. + * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. * `name`: the name or hash of the resource to change. * `should`: a hash of the desired state of the attributes. * `delete(context, name)`: This is called when a resource should be deleted. - * `context`: provides utilties from the runtime environment, and is decribed in more detail there. + * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. * `name`: the name or hash of the resource that should be deleted. The `SimpleProvider` takes care of basic logging, and error handling. @@ -265,7 +264,7 @@ The runtime environment needs to compare user input from the manifest (the desir The `canonicalize` method transforms its `resources` argument into the standard format required by the rest of the provider. The `resources` argument to `canonicalize` is an enumerable of resource hashes matching the structure returned by `get`. It returns all passed values in the same structure with the required transformations applied. It is free to reuse or recreate the data structures passed in as arguments. The runtime environment must use `canonicalize` before comparing user input values with values returned from `get`. The runtime environment always passes canonicalized values into `set`. If the runtime environment requires the original values for later processing, it protects itself from modifications to the objects passed into `canonicalize`, for example through creating a deep copy of the objects. -The `context` parameter is the same passed to `get` and `set`, which provides utilties from the runtime environment, and is decribed in more detail there. +The `context` parameter is the same passed to `get` and `set`, which provides utilities from the runtime environment, and is described in more detail there. > Note: When the provider implements canonicalization, it aims to always log the canonicalized values. As a result of `get` and `set` producing and consuming canonically formatted values, this is not expected to present extra cost. From 563c50cb59ce82e2978dcc67ba9eb45cea99c56d Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Tue, 18 Jun 2019 11:25:57 +0100 Subject: [PATCH 02/11] (maint) Reformat `get` definition for easier readability Break up the dense information from the paragraph into a bulleted list. This ensures that the different statements do not run into each other. --- language/resource-api/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 1c65569..a4c97fb 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -175,7 +175,11 @@ class Puppet::Provider::AptKey::AptKey end ``` -The `get` method reports the current state of the managed resources. It returns an enumerable of all existing resources. Each resource is a hash with attribute names as keys, and their respective values as values. It is an error to return values not matching the type specified in the resource type. If a requested resource is not listed in the result, it is considered to not exist on the system. If the `get` method raises an exception, the provider is marked as unavailable during the current run, and all resources of this type will fail in the current transaction. The exception message will be reported to the user. +The `get` method reports the current state of the managed resources. It returns an enumerable of all existing resources. Each resource is a hash with attribute names as keys, and their respective values as values. + +* It is an error to return values not matching the type specified in the resource type. +* If a requested resource is not listed in the result, it is considered to not exist on the system. +* If the `get` method raises an exception, the provider is marked as unavailable during the current run, and all resources of this type will fail in the current transaction. The exception message will be reported to the user. The `set` method updates resources to a new state. The `changes` parameter gets passed a hash of change requests, keyed by the resource's name. Each value is another hash with the optional `:is` and `:should` keys. At least one of the two has to be specified. The values will be of the same shape as those returned by `get`. After the `set`, all resources should be in the state defined by the `:should` values. From eb55e457fb5688391561fbfa0d40d0be868efc2f Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Tue, 18 Jun 2019 15:16:15 +0100 Subject: [PATCH 03/11] (maint) The `source` attribute is a parameter Improve the initial type schema example. --- language/resource-api/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index a4c97fb..788f3fa 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -37,6 +37,7 @@ Puppet::ResourceApi.register_type( }, source: { type: 'String', + behaviour: :parameter, desc: 'Where to retrieve the key from, can be a HTTP(s) URL, or a local file. Files get automatically required.', }, # ... From 25b809ad9375dfadffac2017c14c0d743083b26a Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Tue, 18 Jun 2019 15:17:23 +0100 Subject: [PATCH 04/11] (maint) Add a example for `set` `changes` argument --- language/resource-api/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 788f3fa..0c81f78 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -184,6 +184,24 @@ The `get` method reports the current state of the managed resources. It returns The `set` method updates resources to a new state. The `changes` parameter gets passed a hash of change requests, keyed by the resource's name. Each value is another hash with the optional `:is` and `:should` keys. At least one of the two has to be specified. The values will be of the same shape as those returned by `get`. After the `set`, all resources should be in the state defined by the `:should` values. +> Example for a `changes` request: +> ``` +> changes = { +> 'name' => { +> is: { +> name: 'name', +> ensure: 'present', +> value: 'original value, +> }, +> should: { +> name: 'name', +> ensure: 'present', +> value: 'new value, +> }, +> }, +> } +> ``` + A missing `:should` entry indicates that a resource should be removed from the system. Even a type implementing the `ensure => [present, absent]` attribute pattern still has to react correctly on a missing `:should` entry. `:is` may contain the last available system state from a prior `get` call. If the `:is` value is `nil`, the resources were not found by `get`. If there is no `:is` key, the runtime did not have a cached state available. The `set` method should always return `nil`. Any progress signaling should be done through the logging utilities described below. If the `set` method throws an exception, all resources that should change in this call and haven't already been marked with a definite state, will be marked as failed. The runtime will only call the `set` method if there are changes to be made, especially in the case of resources marked with `noop => true` (either locally or through a global flag). The runtime will not pass them to `set`. See `supports_noop` below for changing this behaviour if required. From a2f8049b81e3338c6df49f28dca5ae3fbb653b04 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Tue, 18 Jun 2019 20:03:34 +0100 Subject: [PATCH 05/11] (maint) Refactor the description of the SimpleProvider methods to have less duplication --- language/resource-api/README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 0c81f78..7c72032 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -230,18 +230,14 @@ class Puppet::Provider::AptKey::AptKey < Puppet::ResourceApi::SimpleProvider Once all of that is in place, instead of the `set` method, the provider needs to implement the `create`, `update` or `delete` methods: * `create(context, name, should)`: This is called when a new resource should be created. - * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. - * `name`: the name or hash of the new resource. - * `should`: a hash of the attributes for the new instance. - * `update(context, name, should)`: This is called when a resource should be updated. - * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. - * `name`: the name or hash of the resource to change. - * `should`: a hash of the desired state of the attributes. - * `delete(context, name)`: This is called when a resource should be deleted. - * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. - * `name`: the name or hash of the resource that should be deleted. + +The parameters of these methods always carry the same values: + +* `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. +* `name`: the name (if there is only one namevar) or hash of namevars (if there are multiple) of the new resource. +* `should`: a hash of the desired state of the attributes. This is not passed to the delete method. The `SimpleProvider` takes care of basic logging, and error handling. From c1a108a4b318a2da5f034dffb35195a6498033dd Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Tue, 18 Jun 2019 20:47:44 +0100 Subject: [PATCH 06/11] (maint) Fix up and extend example for `canonicalize` --- language/resource-api/README.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 7c72032..f314c41 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -270,11 +270,11 @@ Puppet::ResourceApi.register_type( class Puppet::Provider::AptKey::AptKey def canonicalize(context, resources) resources.each do |r| - r[:name] = if r[:name].start_with?('0x') - r[:name][2..-1].upcase - else - r[:name].upcase - end + r[:id] = if r[:id].start_with?('0x') + r[:id][2..-1].upcase + else + r[:id].upcase + end end end ``` @@ -285,6 +285,20 @@ The `canonicalize` method transforms its `resources` argument into the standard The `context` parameter is the same passed to `get` and `set`, which provides utilities from the runtime environment, and is described in more detail there. +> Example: The `resources` parameter is an array of resources hashes: +> ```ruby +> resources = [ +> { +> id: '0x12345678', +> source: '/net/gold/example.com/www/key1.gpg', +> }, +> { +> id: '1234567812345678123456781234567812345678', +> source: '/net/gold/example.com/www/key2.gpg', +> }, +> ] +> ``` + > Note: When the provider implements canonicalization, it aims to always log the canonicalized values. As a result of `get` and `set` producing and consuming canonically formatted values, this is not expected to present extra cost. A side effect of these rules is that the canonicalization of `get`'s return value must not change the processed values. From 8df53508c6b725de5e1144270910b555cd9e6462 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 24 May 2019 14:25:43 +0100 Subject: [PATCH 07/11] (MODULES-9428) Clarify composite namevar edgecases and add examples * Point out that there can be more than two namevars * Improve composite namevar example This is rewording doc strings, fixing syntax errors, and reformatting the example. * Clarify behaviour when no `title_pattern` is specified Make sure to communicate the behaviour and consequences when no `title_patterns` are specified. * Upgraded the "order" note to a definitive statement on the matching behaviour. * Update the description for `get` and `set` for composite namevars This moves the existing explanation for how `get` should behave to the definition of the method and adds examples for the values passed around by `get` and `set`. * Mention again that composite namevars are supported by SimpleProvider * Remove the `title` key from the hash being passed to SimpleProvider methods Since we can't guarantee to always have a title available, we can't promise to pass one through to the implementation. * Add a note and examples about `names` usage in `simple_get_filter` This also covers PDK-1219, PDK-1220, and PDK-1221. --- language/resource-api/README.md | 76 +++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index f314c41..3bdced2 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -74,11 +74,12 @@ For autoloading to work, this code needs to go into `lib/puppet/type/.rb` ### Composite Namevars ("title_patterns") -Each resource being managed must be identified by a unique title. Usually this is fairly straightforward and a single attribute can be used to act as an identifier. Sometimes though, you need a composite of two attributes to uniquely identify the resource you want to manage. +Each resource being managed must be identified by a unique title. Usually this is fairly straightforward and a single attribute can be used to act as an identifier. Sometimes though, you need a composite of two or more attributes to uniquely identify the resource you want to manage. -If multiple attributes are defined with the `namevar` behaviour, the type SHOULD specify `title_patterns` that will tell Resource API how to get at the attributes from the title. If `title_patterns` is not specified a default pattern is applied, and matches against the first declared `namevar`. +If multiple attributes are defined with the `namevar` behaviour, the type SHOULD specify `title_patterns` that will tell Resource API how to get at the attributes from the title. If `title_patterns` is not specified a default pattern is applied, and matches the entire title against the first declared `namevar`. +> Note: Not supplying a title_pattern that assigns values to all namevars will severely restrict the usability of the provider. -> Note: The order of title_patterns is important. You should declare the most specific pattern first and end with the most generic. +The title_patterns are evaluated in the order they are specified. Evaluation stops after the first match is achieved. Each title pattern contains the: * `pattern`, which is a ruby regex containing named captures. The names of the captures MUST be that of the namevar attributes. @@ -96,7 +97,7 @@ Puppet::ResourceApi.register_type( title_patterns: [ { pattern: %r{^(?.*[^-])-(?.*)$}, - desc: 'Where the package and the manager are provided with a hyphen separator', + desc: 'Where the package and the manager are separated by a hyphen', }, { pattern: %r{^(?.*)$}, @@ -127,19 +128,20 @@ Matches the first title pattern: ```puppet # /etc/puppetlabs/code/environments/production/manifests/site.pp software { php-yum: - ensure=>'present' + ensure => 'present', } software { php-gem: - ensure=>'absent' + ensure => 'absent', } ``` + Matches the second title pattern: ```puppet # /etc/puppetlabs/code/environments/production/manifests/site.pp software { php: - manager='yum' - ensure=>'present' + ensure => 'present', + manager => 'yum', } ``` @@ -181,6 +183,18 @@ The `get` method reports the current state of the managed resources. It returns * It is an error to return values not matching the type specified in the resource type. * If a requested resource is not listed in the result, it is considered to not exist on the system. * If the `get` method raises an exception, the provider is marked as unavailable during the current run, and all resources of this type will fail in the current transaction. The exception message will be reported to the user. +* If the type has more than one namevar, each resource hash must have a `:title` key with a single formatted string representing all namevar values. The title must match one of the title patterns. The namevar values computed from that pattern must match their counterparts in the hash. + > Note: This value allows the runtime environment to present resources in a way familiar to the user. + + > Example: Referring back to the `software` example above, resources returned from the `get` method require a `title:` value matching the `package:` and `manager:` values: + > ``` + > { + > title: 'php-yum', + > package: 'php', + > manager: 'yum', + > ensure: 'present', + > } + > ``` The `set` method updates resources to a new state. The `changes` parameter gets passed a hash of change requests, keyed by the resource's name. Each value is another hash with the optional `:is` and `:should` keys. At least one of the two has to be specified. The values will be of the same shape as those returned by `get`. After the `set`, all resources should be in the state defined by the `:should` values. @@ -204,6 +218,28 @@ The `set` method updates resources to a new state. The `changes` parameter gets A missing `:should` entry indicates that a resource should be removed from the system. Even a type implementing the `ensure => [present, absent]` attribute pattern still has to react correctly on a missing `:should` entry. `:is` may contain the last available system state from a prior `get` call. If the `:is` value is `nil`, the resources were not found by `get`. If there is no `:is` key, the runtime did not have a cached state available. +If a type has more than one namevar, the resource's name key is replaced by a hash of the namevars and their values: + +> Example for a `changes` request with multiple namevars: +> ``` +> changes = { +> { package: 'php', manager: 'yum' } => { +> is: { +> package: 'php', +> manager: 'yum', +> ensure: 'present', +> value: 'original value, +> }, +> should: { +> package: 'php', +> manager: 'yum', +> ensure: 'present', +> value: 'new value, +> }, +> }, +> } +> ``` + The `set` method should always return `nil`. Any progress signaling should be done through the logging utilities described below. If the `set` method throws an exception, all resources that should change in this call and haven't already been marked with a definite state, will be marked as failed. The runtime will only call the `set` method if there are changes to be made, especially in the case of resources marked with `noop => true` (either locally or through a global flag). The runtime will not pass them to `set`. See `supports_noop` below for changing this behaviour if required. Both methods take a `context` parameter which provides utilities from the runtime environment, and is described in more detail in its own section below. @@ -214,7 +250,7 @@ In many cases, the resource type follows the conventional patterns of puppet, an `SimpleProvider` requires that your type follows some common conventions: -* `name` is the name of your namevar attribute +* the single namevar attribute is called `name` or the type has more than one namevar * `ensure` attribute is present and has the `Enum[absent, present]` type To start using `SimpleProvider`, inherit from the class like this: @@ -222,7 +258,7 @@ To start using `SimpleProvider`, inherit from the class like this: ```ruby require 'puppet/resource_api/simple_provider' -# Implementation for the wordarray type using the Resource API. +# Implementation for the apt_key type using the Resource API. class Puppet::Provider::AptKey::AptKey < Puppet::ResourceApi::SimpleProvider # ... ``` @@ -241,11 +277,10 @@ The parameters of these methods always carry the same values: The `SimpleProvider` takes care of basic logging, and error handling. -When a `type` has only a single namevar defined, `SimpleProvider` will pass the value of that attribute as `name` to the `create`, `update` and `delete` methods. If multiple namevars are defined, `SimpleProvider` will instead pass a hash. The hash contains the composite name of `title`, and all the namevars and their values, for example: +When a `type` has only a single namevar defined, `SimpleProvider` will pass the value of that attribute as `name` to the `create`, `update` and `delete` methods. If multiple namevars are defined, `SimpleProvider` will instead pass a hash. The hash contains all the namevars and their values, for example: ``` { - title: 'foo/bar', name: 'bar', group: 'foo', } @@ -336,17 +371,22 @@ Puppet::ResourceApi.register_type( # lib/puppet/provider/apt_key/apt_key.rb class Puppet::Provider::AptKey::AptKey def get(context, names = nil) - [ - { - name: 'name', - # ... - }, - ] + if names == nil + return all_instances + else + names.collect { |n| find_instance(n) } + end end ``` Some resources are very expensive to enumerate. The provider can implement `simple_get_filter` to signal extended capabilities of the `get` method to address this. The provider's `get` method will be called with an array of resource names, or `nil`. The `get` method must at least return the resources mentioned in the `names` array, but may return more than those. If the `names` parameter is `nil`, all existing resources should be returned. The `names` parameter defaults to `nil` to allow simple runtimes to ignore this feature. +For types with multiple namevars, the `names` array will consist of hashes of the namevars and their variables instead of simple values: + +```ruby +[ { package: 'php', manager: 'yum' }, {package: 'mysql', manager: 'yum'} ] +``` + The runtime environment calls `get` with a minimal set of names, and keeps track of additional instances returned to avoid double querying. To gain the most benefits from batching implementations, the runtime minimizes the number of calls into `get`. ### Provider feature: `supports_noop` From 2b972295895aa769f59e0272f7d525e7b4de68a7 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Wed, 19 Jun 2019 15:52:17 +0100 Subject: [PATCH 08/11] (maint) remove noop parameter from remote_resource example The remote_resource example had remnants from a supports_noop implementation. This change removes those remnants as they are misleading and do not add value to this example. --- language/resource-api/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 3bdced2..c16abdf 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -425,12 +425,12 @@ Puppet::ResourceApi.register_type( # lib/puppet/provider/nx9k_vlan/nexus.rb class Puppet::Provider::Nx9k_vlan::Nexus - def set(context, changes, noop: false) + def set(context, changes) changes.each do |name, change| is = change.has_key? :is ? change[:is] : get_single(name) should = change[:should] # ... - context.transport.do_something unless noop + context.transport.do_something end end ``` From 592d7c2f5027d32f4cab5df82499c02aaf0d6448 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 20 Jun 2019 16:31:40 +0100 Subject: [PATCH 09/11] (MODULES-9428) Improvements from review * Fixed quoting in examples * Improve wording in a couple of places --- language/resource-api/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index c16abdf..e8c8730 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -205,12 +205,12 @@ The `set` method updates resources to a new state. The `changes` parameter gets > is: { > name: 'name', > ensure: 'present', -> value: 'original value, +> value: 'original value', > }, > should: { > name: 'name', > ensure: 'present', -> value: 'new value, +> value: 'new value', > }, > }, > } @@ -228,13 +228,13 @@ If a type has more than one namevar, the resource's name key is replaced by a ha > package: 'php', > manager: 'yum', > ensure: 'present', -> value: 'original value, +> value: 'original value', > }, > should: { > package: 'php', > manager: 'yum', > ensure: 'present', -> value: 'new value, +> value: 'new value', > }, > }, > } @@ -250,7 +250,7 @@ In many cases, the resource type follows the conventional patterns of puppet, an `SimpleProvider` requires that your type follows some common conventions: -* the single namevar attribute is called `name` or the type has more than one namevar +* if the type has a single namevar attribute, it must be called `name` * `ensure` attribute is present and has the `Enum[absent, present]` type To start using `SimpleProvider`, inherit from the class like this: @@ -272,7 +272,7 @@ Once all of that is in place, instead of the `set` method, the provider needs to The parameters of these methods always carry the same values: * `context`: provides utilities from the runtime environment, and is described in more detail in its own section below. -* `name`: the name (if there is only one namevar) or hash of namevars (if there are multiple) of the new resource. +* `name`: the name (if there is only one namevar) or hash of namevars (if there are multiple) of the resource. * `should`: a hash of the desired state of the attributes. This is not passed to the delete method. The `SimpleProvider` takes care of basic logging, and error handling. @@ -318,7 +318,7 @@ The runtime environment needs to compare user input from the manifest (the desir The `canonicalize` method transforms its `resources` argument into the standard format required by the rest of the provider. The `resources` argument to `canonicalize` is an enumerable of resource hashes matching the structure returned by `get`. It returns all passed values in the same structure with the required transformations applied. It is free to reuse or recreate the data structures passed in as arguments. The runtime environment must use `canonicalize` before comparing user input values with values returned from `get`. The runtime environment always passes canonicalized values into `set`. If the runtime environment requires the original values for later processing, it protects itself from modifications to the objects passed into `canonicalize`, for example through creating a deep copy of the objects. -The `context` parameter is the same passed to `get` and `set`, which provides utilities from the runtime environment, and is described in more detail there. +The `context` parameter provides utilities from the runtime environment, and is described in more detail there. It is the same as is passed to `get` and `set`. > Example: The `resources` parameter is an array of resources hashes: > ```ruby @@ -381,7 +381,7 @@ class Puppet::Provider::AptKey::AptKey Some resources are very expensive to enumerate. The provider can implement `simple_get_filter` to signal extended capabilities of the `get` method to address this. The provider's `get` method will be called with an array of resource names, or `nil`. The `get` method must at least return the resources mentioned in the `names` array, but may return more than those. If the `names` parameter is `nil`, all existing resources should be returned. The `names` parameter defaults to `nil` to allow simple runtimes to ignore this feature. -For types with multiple namevars, the `names` array will consist of hashes of the namevars and their variables instead of simple values: +For types with multiple namevars, the `names` array will consist of hashes of the namevars and their values instead of simple values: ```ruby [ { package: 'php', manager: 'yum' }, {package: 'mysql', manager: 'yum'} ] From f99d267b79bb27b3739d2fff5ebb39696326c727 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Tue, 25 Jun 2019 15:48:03 +0100 Subject: [PATCH 10/11] (MODULES-9428) Make title_patterns mandatory After conversation with Henrik, I'm certain that we should not burden the text or code with the complexity of having title_patterns optional. --- language/resource-api/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index e8c8730..33f38fd 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -76,10 +76,9 @@ For autoloading to work, this code needs to go into `lib/puppet/type/.rb` Each resource being managed must be identified by a unique title. Usually this is fairly straightforward and a single attribute can be used to act as an identifier. Sometimes though, you need a composite of two or more attributes to uniquely identify the resource you want to manage. -If multiple attributes are defined with the `namevar` behaviour, the type SHOULD specify `title_patterns` that will tell Resource API how to get at the attributes from the title. If `title_patterns` is not specified a default pattern is applied, and matches the entire title against the first declared `namevar`. -> Note: Not supplying a title_pattern that assigns values to all namevars will severely restrict the usability of the provider. +If multiple attributes are defined with the `namevar` behaviour, the type must specify `title_patterns` that will tell Resource API how to get at the attributes from the title. -The title_patterns are evaluated in the order they are specified. Evaluation stops after the first match is achieved. +The `title_patterns` are evaluated in the order they are specified. Evaluation stops after the first match is achieved. Each title pattern contains the: * `pattern`, which is a ruby regex containing named captures. The names of the captures MUST be that of the namevar attributes. From dfc520ae5c6714b9bc467ffbf68bc6daef7896e6 Mon Sep 17 00:00:00 2001 From: Dave Armstrong Date: Fri, 28 Jun 2019 11:41:41 +0100 Subject: [PATCH 11/11] (maint) Minor update to `changes` example --- language/resource-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/language/resource-api/README.md b/language/resource-api/README.md index 33f38fd..0ab22f5 100644 --- a/language/resource-api/README.md +++ b/language/resource-api/README.md @@ -200,14 +200,14 @@ The `set` method updates resources to a new state. The `changes` parameter gets > Example for a `changes` request: > ``` > changes = { -> 'name' => { +> 'foo' => { > is: { -> name: 'name', +> name: 'foo', > ensure: 'present', > value: 'original value', > }, > should: { -> name: 'name', +> name: 'foo', > ensure: 'present', > value: 'new value', > },