summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2022-03-31 20:59:05 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2022-03-31 21:34:02 -0700
commit6b4a7d207708173314b089a8650c05183b6ce813 (patch)
tree371568c2a77888cc22bb10930ade989742a4b4d7
parentc604b38a8b2f32be793f6f0d7defa049361d241b (diff)
downloadchef-6b4a7d207708173314b089a8650c05183b6ce813.tar.gz
remove LWRP cruft
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r--lib/chef/provider/rest_resource.rb371
-rw-r--r--lib/chef/providers.rb1
-rw-r--r--lib/chef/resource/rest_resource.rb22
-rw-r--r--lib/chef/resources.rb1
4 files changed, 0 insertions, 395 deletions
diff --git a/lib/chef/provider/rest_resource.rb b/lib/chef/provider/rest_resource.rb
deleted file mode 100644
index 02801f7efd..0000000000
--- a/lib/chef/provider/rest_resource.rb
+++ /dev/null
@@ -1,371 +0,0 @@
-require_relative "../provider"
-require "rest-client" unless defined?(RestClient)
-require "jmespath" unless defined?(JMESPath)
-
-class Chef
- class Provider
- class RestResource < Chef::Provider
- attr_writer :current_resource
-
- def load_current_resource
- @current_resource = new_resource.class.new(new_resource.name)
-
- required_properties.each do |name|
- requested = new_resource.send(name)
- current_resource.send(name, requested)
- end
-
- return @current_resource if rest_get_all.data.empty?
-
- resource_data = rest_get.data rescue nil
- return @current_resource if resource_data.nil? || resource_data.empty?
-
- @resource_exists = true
-
- # Map JSON contents to defined properties
- current_resource.class.rest_property_map.each do |property, match_instruction|
- property_value = json_to_property(match_instruction, property, resource_data)
- current_resource.send(property, property_value) unless property_value.nil?
- end
-
- current_resource
- end
-
- action :configure do
- if resource_exists?
- converge_if_changed do
- data = {}
-
- new_resource.class.rest_property_map.each do |property, match_instruction|
- # Skip "creation-only" properties on modifications
- next if new_resource.class.rest_post_only_properties.include?(property)
-
- deep_merge! data, property_to_json(property, match_instruction)
- end
-
- deep_compact!(data)
-
- rest_patch(data)
- end
- else
- converge_by "creating resource" do
- data = {}
-
- new_resource.class.rest_property_map.each do |property, match_instruction|
- deep_merge! data, property_to_json(property, match_instruction)
- end
-
- deep_compact!(data)
-
- rest_post(data)
- end
- end
- end
-
- action :delete do
- if resource_exists?
- converge_by "deleting resource" do
- rest_delete
- end
- else
- logger.debug format("REST resource %<name>s of type %<type>s does not exist. Skipping.",
- type: new_resource.name, name: id_property)
- end
- end
-
- protected
-
- def resource_exists?
- @resource_exists
- end
-
- def required_properties
- current_resource.class.properties.select { |_, v| v.required? }.except(:name).keys
- end
-
- # Return changed value or nil for delta current->new
- def changed_value(property)
- new_value = new_resource.send(property)
- return new_value if current_resource.nil?
-
- current_value = current_resource.send(property)
-
- return current_value if required_properties.include? property
-
- new_value == current_value ? nil : new_value
- end
-
- def id_property
- current_resource.class.identity_attr
- end
-
- # Map properties to their current values
- def property_map
- map = {}
-
- current_resource.class.state_properties.each do |property|
- name = property.options[:name]
-
- map[name] = current_resource.send(name)
- end
-
- map[id_property] = current_resource.send(id_property)
-
- map
- end
-
- # Map part of a JSON (Hash) to resource property via JMESPath or user-supplied function
- def json_to_property(match_instruction, property, resource_data)
- case match_instruction
- when String
- JMESPath.search(match_instruction, resource_data)
- when Symbol
- function = "#{property}_from_json".to_sym
- raise "#{new_resource.name} missing #{function} method" unless self.class.protected_method_defined?(function)
-
- send(function, resource_data) || {}
- else
- raise TypeError, "Did not expect match type #{match_instruction.class}"
- end
- end
-
- # Map resource contents into a JSON (Hash) via JMESPath-like syntax or user-supplied function
- def property_to_json(property, match_instruction)
- case match_instruction
- when String
- bury(match_instruction, changed_value(property))
- when Symbol
- function = "#{property}_to_json".to_sym
- raise "#{new_resource.name} missing #{function} method" unless self.class.protected_method_defined?(function)
-
- value = new_resource.send(property)
- changed_value(property).nil? ? {} : send(function, value)
- else
- raise TypeError, "Did not expect match type #{match_instruction.class}"
- end
- end
-
- def rest_url_collection
- current_resource.class.rest_api_collection
- end
-
- # Resource document URL after RFC 6570 template evaluation via properties substitution
- def rest_url_document
- template = ::Addressable::Template.new(current_resource.class.rest_api_document)
- template.expand(property_map).to_s
- end
-
- # Convenience method for conditional requires
- def conditionally_require_on_setting(property, dependent_properties)
- dependent_properties = Array(dependent_properties)
-
- requirements.assert(:configure) do |a|
- a.assertion do
- # Needs to be set and truthy to require dependent properties
- if new_resource.send(property)
- dependent_properties.all? { |dep_prop| new_resource.property_is_set?(dep_prop) }
- else
- true
- end
- end
-
- message = format("Setting property :%<property>s requires properties :%<properties>s to be set as well on resource %<resource_name>s",
- property: property,
- properties: dependent_properties.join(", :"),
- resource_name: current_resource.to_s)
-
- a.failure_message message
- end
- end
-
- # Generic REST helpers
-
- def rest_get_all
- response = api_connection.get(rest_url_collection)
-
- rest_postprocess(response)
- rescue RestClient::Exception => e
- rest_errorhandler(e)
- end
-
- def rest_get
- response = api_connection.get(rest_url_document)
-
- response = rest_postprocess(response)
-
- first_only = current_resource.class.rest_api_document_first_element_only
- first_only && response.is_a?(Array) ? response.first : response
- rescue RestClient::Exception => e
- rest_errorhandler(e)
- end
-
- def rest_post(data)
- data.merge! rest_identity_values
-
- response = api_connection.post(rest_url_collection, data: data)
-
- rest_postprocess(response)
- rescue RestClient::Exception => e
- rest_errorhandler(e)
- end
-
- def rest_put(data)
- data.merge! rest_identity_values
-
- response = api_connection.put(rest_url_collection, data: data)
-
- rest_postprocess(response)
- rescue RestClient::Exception => e
- rest_errorhandler(e)
- end
-
- def rest_patch(data)
- response = api_connection.patch(rest_url_document, data: data)
-
- rest_postprocess(response)
- rescue RestClient::Exception => e
- rest_errorhandler(e)
- end
-
- def rest_delete
- response = api_connection.delete(rest_url_document)
-
- rest_postprocess(response)
- rescue RestClient::Exception => e
- rest_errorhandler(e)
- end
-
- # REST parameter mapping
-
- # Return number of parameters needed to identify a resource (pre- and post-creation)
- def rest_arity
- rest_identity_map.keys.count
- end
-
- # Return mapping of template placeholders to property value of identity parameters
- def rest_identity_values
- data = {}
-
- rest_identity_map.each do |rfc_template, property|
- property_value = new_resource.send(property)
- data.merge! bury(rfc_template, property_value)
- end
-
- data
- end
-
- def rest_identity_map
- rest_identity_explicit || rest_identity_implicit
- end
-
- # Accept direct mapping like { "svm.name" => :name } for specifying the x-ary identity of a resource
- def rest_identity_explicit
- current_resource.class.rest_identity_map
- end
-
- # Parse document URL for RFC 6570 templates and map them to resource properties.
- #
- # Examples:
- # Query based: "/api/protocols/san/igroups?name={name}&svm.name={svm}": { "name" => :name, "svm.name" => :svm }
- # Path based: "/api/v1/{address}": { "address" => :address }
- #
- def rest_identity_implicit
- template_url = current_resource.class.rest_api_document
-
- rfc_template = ::Addressable::Template.new(template_url)
- rfc_template_vars = rfc_template.variables
-
- # Shortcut for 0-ary resources
- return {} if rfc_template_vars.empty?
-
- if query_based_selection?
- uri_query = URI.parse(template_url).query
-
- if CGI.parse(uri_query).values.any?(&:empty?)
- raise "Need explicit identity mapping, as URL does not contain query parameters for all templates"
- end
-
- path_variables = CGI.parse(uri_query).keys
- elsif path_based_selection?
- path_variables = rfc_template_vars
- else
- # There is also
- raise "Unknown type of resource selection. Document URL does not seem to be path- or query-based?"
- end
-
- identity_map = {}
- path_variables.each_with_index do |v, i|
- next if rfc_template_vars[i].nil? # Not mapped to property, assume metaparameter
-
- identity_map[v] = rfc_template_vars[i].to_sym
- end
-
- identity_map
- end
-
- def query_based_selection?
- template_url = current_resource.class.rest_api_document
-
- # Will throw exception on presence of RFC 6570 templates
- URI.parse(template_url)
- true
- rescue URI::InvalidURIError => _e
- false
- end
-
- def path_based_selection?
- !query_based_selection?
- end
-
- def api_connection
- Chef.run_context.transport.connection
- end
-
- # Override this for postprocessing device-specifics (paging, data conversion)
- def rest_postprocess(response)
- response
- end
-
- # Override this for error handling of device-specifics (readable error messages)
- def rest_errorhandler(error_obj)
- error_obj
- end
-
- # Remove all empty keys (recusively) from Hash.
- # @see https://stackoverflow.com/questions/56457020/#answer-56458673
- def deep_compact!(hsh)
- raise TypeError unless hsh.is_a? Hash
-
- hsh.each do |_, v|
- deep_compact!(v) if v.is_a? Hash
- end.reject! { |_, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }
- end
-
- # Deep merge two hashes
- # @see https://stackoverflow.com/questions/41109599#answer-41109737
- def deep_merge!(hsh1, hsh2)
- raise TypeError unless hsh1.is_a?(Hash) && hsh2.is_a?(Hash)
-
- hsh1.merge!(hsh2) { |_, v1, v2| deep_merge!(v1, v2) }
- end
-
- # Create nested hashes from JMESPath syntax.
- def bury(path, value)
- raise TypeError unless path.is_a?(String)
-
- arr = path.split(".")
- ret = {}
-
- if arr.count == 1
- ret[arr.first] = value
-
- ret
- else
- partial_path = arr[0..-2].join(".")
-
- bury(partial_path, bury(arr.last, value))
- end
- end
- end
- end
-end
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index 09a1380760..e713383190 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -38,7 +38,6 @@ require_relative "provider/package"
require_relative "provider/powershell_script"
require_relative "provider/remote_directory"
require_relative "provider/remote_file"
-require_relative "provider/rest_resource"
require_relative "provider/route"
require_relative "provider/ruby_block"
require_relative "provider/script"
diff --git a/lib/chef/resource/rest_resource.rb b/lib/chef/resource/rest_resource.rb
deleted file mode 100644
index 1993d12ce8..0000000000
--- a/lib/chef/resource/rest_resource.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require_relative "../resource"
-require_relative "../dsl/rest_resource"
-
-class Chef
- class Resource
- class RestResource < Chef::Resource
- unified_mode true
-
- # This is an abstract resource meant to be subclassed; thus no 'provides'
-
- skip_docs true
- preview_resource true
-
- description "Generic superclass for all REST API resources"
-
- default_action :configure
- allowed_actions :configure, :delete
-
- include Chef::DSL::RestResource
- end
- end
-end
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index cc18b60c9f..ac5ec5d8e0 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -112,7 +112,6 @@ require_relative "resource/reboot"
require_relative "resource/registry_key"
require_relative "resource/remote_directory"
require_relative "resource/remote_file"
-require_relative "resource/rest_resource"
require_relative "resource/rhsm_errata_level"
require_relative "resource/rhsm_errata"
require_relative "resource/rhsm_register"