diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2022-03-31 20:59:05 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2022-03-31 21:34:02 -0700 |
commit | 6b4a7d207708173314b089a8650c05183b6ce813 (patch) | |
tree | 371568c2a77888cc22bb10930ade989742a4b4d7 | |
parent | c604b38a8b2f32be793f6f0d7defa049361d241b (diff) | |
download | chef-6b4a7d207708173314b089a8650c05183b6ce813.tar.gz |
remove LWRP cruft
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r-- | lib/chef/provider/rest_resource.rb | 371 | ||||
-rw-r--r-- | lib/chef/providers.rb | 1 | ||||
-rw-r--r-- | lib/chef/resource/rest_resource.rb | 22 | ||||
-rw-r--r-- | lib/chef/resources.rb | 1 |
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" |