All Files
(99.63%
covered at
11.89
hits/line)
3 files in total.
273 relevant lines.
272 lines covered and
1 lines missed
Libraries
(99.63%
covered at
11.89
hits/line)
3 files in total.
273 relevant lines.
272 lines covered and
1 lines missed
-
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
-
#
-
# Licensed under the Apache License, Version 2.0 (the "License");
-
# you may not use this file except in compliance with the License.
-
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-
#
-
# Unless required by applicable law or agreed to in writing, software distributed
-
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
-
# specific language governing permissions and limitations under the License.
-
-
1
require 'logger'
-
-
1
module OneviewCookbook
-
# Helpers for Oneview Resources
-
1
module Helper
-
# Get resource class that matches the type given
-
# @param [String] type Name of the desired class type
-
# @param [Module] api_module Module who the desired class type belongs to
-
# @param [String] variant Variant (C7000 or Synergy)
-
# @raise [RuntimeError] if resource class not found
-
# @return [Class] Resource class
-
1
def self.get_provider_named(type, api_module, variant = nil)
-
8
api_version = api_module.to_s.split('::').last
-
8
if variant
-
7
raise "#{api_version} variant #{variant} is not supported!" unless api_module::SUPPORTED_VARIANTS.include?(variant.to_s)
-
6
api_module = api_module.const_get(variant.to_s)
-
end
-
7
new_type = type.to_s.downcase.gsub(/[ -_]/, '') + 'provider'
-
7
api_module.constants.each do |c|
-
199
klass = api_module.const_get(c)
-
199
next unless klass.is_a?(Class) && klass < OneviewCookbook::ResourceProvider
-
197
name = klass.name.split('::').last.downcase.delete('_').delete('-')
-
197
return klass if new_type =~ /^#{name}$/
-
end
-
1
raise "The '#{type}' resource does not exist for OneView #{api_version}, variant #{variant}."
-
end
-
-
# All-in-one method for performing an action on a resource
-
# @param context Context from the resource action block (self)
-
# @param [String, Symbol] type Name of the resource type. e.g., :EthernetNetwork
-
# @param [String, Symbol] action Action method to call on the resource. e.g., :create_or_update
-
# @param [Module] base_module The base API module supported. e.g. OneviewCookbook::ImageStreamer
-
1
def self.do_resource_action(context, type, action, base_module = OneviewCookbook)
-
1
klass = OneviewCookbook::Helper.get_resource_class(context, type, base_module)
-
1
res = klass.new(context)
-
1
res.send(action)
-
end
-
-
# Get the resource class by name, taking into consideration the resource's properties
-
# @param context Context from the resource action block (self)
-
# @param [String, Symbol] type Name of the resource type. e.g., :EthernetNetwork
-
# @param [Module] base_module The base API module supported. e.g. OneviewCookbook::ImageStreamer
-
# @return [Class] Resource class
-
1
def self.get_resource_class(context, resource_type, base_module = OneviewCookbook)
-
5
load_sdk(context)
-
# Loads the api version if the property was specified directly
-
5
context_api_version = context.new_resource.api_version if context.property_is_set?(:api_version)
-
# Loads the api version if it was specified in the client
-
5
client_api_version = if context.property_is_set?(:client)
-
2
if context.new_resource.client.is_a?(Hash)
-
1
convert_keys(context.new_resource.client, :to_sym)[:api_version]
-
1
elsif context.new_resource.client.is_a?(OneviewSDK::Client) # It works for both Image Streamer and OneView
-
1
context.new_resource.client.api_version
-
end
-
end
-
# Loads the api version giving preference: property > client > node default
-
5
api_version = context_api_version || client_api_version || context.node['oneview']['api_version']
-
5
api_module = get_api_module(api_version, base_module)
-
5
api_variant = context.property_is_set?(:api_variant) ? context.new_resource.api_variant : context.node['oneview']['api_variant']
-
5
api_module.provider_named(resource_type, api_variant)
-
end
-
-
# Get the API module given an api_version
-
# @param [Integer, String] api_version
-
# @param [Module] base_module The base API module supported. e.g. OneviewCookbook::ImageStreamer
-
# @return [Module] Resource module
-
1
def self.get_api_module(api_version, base_module = OneviewCookbook)
-
9
base_module.const_get("API#{api_version}")
-
rescue NameError
-
1
raise NameError, "The api_version #{api_version} is not supported in #{base_module}. Please use a supported version."
-
end
-
-
# Load (and install if necessary) the oneview-sdk
-
# @param context Context from the resource action block (self)
-
1
def self.load_sdk(context)
-
3
node = context.node
-
3
gem 'oneview-sdk', node['oneview']['ruby_sdk_version']
-
1
require 'oneview-sdk'
-
1
Chef::Log.debug("Loaded oneview-sdk #{node['oneview']['ruby_sdk_version']} (#{OneviewSDK::VERSION})")
-
rescue LoadError => e
-
2
Chef::Log.debug("Could not load gem oneview-sdk #{node['oneview']['ruby_sdk_version']}. Message: #{e.message}")
-
2
Chef::Log.info("Could not load gem oneview-sdk #{node['oneview']['ruby_sdk_version']}. Making sure it's installed...")
-
2
context.chef_gem 'oneview-sdk' do
-
1
version node['oneview']['ruby_sdk_version']
-
1
compile_time true if Chef::Resource::ChefGem.method_defined?(:compile_time)
-
end
-
begin # Try to load the specified version of the oneview-sdk gem again
-
2
gem 'oneview-sdk', node['oneview']['ruby_sdk_version']
-
1
require 'oneview-sdk'
-
1
Chef::Log.debug("Loaded oneview-sdk version #{OneviewSDK::VERSION}")
-
rescue LoadError => er
-
1
Chef::Log.error("Version #{node['oneview']['ruby_sdk_version']} of oneview-sdk cannot be loaded. Message: #{er.message}")
-
1
require 'oneview-sdk'
-
1
Chef::Log.error("Loaded version #{OneviewSDK::VERSION} of the oneview-sdk gem instead")
-
end
-
end
-
-
# Makes it easy to build a Client object
-
# @param [Hash, OneviewSDK::Client] client Appliance info hash or client object.
-
# @return [OneviewSDK::Client] Client object
-
1
def self.build_client(client = nil)
-
17
Chef::Log.debug("Building OneView client with:\n#{client}\n\n")
-
17
case client
-
when OneviewSDK::Client
-
8
client
-
when Hash
-
23
options = Hash[client.map { |k, v| [k.to_sym, v] }] # Convert string keys to symbols
-
5
unless options[:logger] # Use the Chef logger
-
4
options[:logger] = Chef::Log
-
4
options[:log_level] = Chef::Log.level
-
end
-
5
options[:log_level] ||= Chef::Log.level
-
5
OneviewSDK::Client.new(options)
-
when NilClass
-
3
options = {}
-
3
options[:logger] = Chef::Log
-
3
options[:log_level] = Chef::Log.level
-
3
OneviewSDK::Client.new(options) # Rely on the ENV variables being set
-
else
-
1
raise "Invalid client #{client}. Must be a hash or OneviewSDK::Client"
-
end
-
end
-
-
# Makes it easy to build a Image Streamer Client object
-
# @param [Hash, OneviewSDK::ImageStreamer::Client] client Appliance info hash or client object.
-
# @return [OneviewSDK::ImageStreamer::Client] Client object
-
1
def self.build_image_streamer_client(client = nil)
-
10
Chef::Log.debug("Building Image Streamer client with:\n#{client}\n\n")
-
10
case client
-
when OneviewSDK::ImageStreamer::Client
-
1
client
-
when Hash
-
22
options = Hash[client.map { |k, v| [k.to_sym, v] }] # Convert string keys to symbols
-
6
unless options[:logger] # Use the Chef logger
-
5
options[:logger] = Chef::Log
-
5
options[:log_level] = Chef::Log.level
-
end
-
6
options[:log_level] ||= Chef::Log.level
-
6
return OneviewSDK::ImageStreamer::Client.new(options) unless options[:oneview_client] # Rely on token being set
-
1
ov_client = build_client(options.delete(:oneview_client))
-
1
OneviewSDK::ImageStreamer::Client.new(options.merge(token: ov_client.token))
-
when NilClass
-
2
options = {}
-
2
options[:logger] = Chef::Log
-
2
options[:log_level] = Chef::Log.level
-
2
OneviewSDK::ImageStreamer::Client.new(options) # Rely on the ENV variables being set
-
else
-
1
raise "Invalid client #{client}. Must be a hash or OneviewSDK::ImageStreamer::Client"
-
end
-
end
-
-
# Utility method that converts Hash symbol to string keys
-
# @param [Hash] info Hash containing the dataset
-
# @param [Symbol] conversion_method Symbol representing the method to be called in the conversion
-
# @return [Hash] Hash with the keys converted. Returns nil if info is invalid.
-
1
def self.convert_keys(info, conversion_method)
-
13
return nil unless info
-
13
support = {}
-
13
info.each do |k, v|
-
24
if v.class == Hash
-
4
con = convert_keys(v, conversion_method)
-
20
elsif v.class == Array
-
3
con = v.map { |h| convert_keys(h, conversion_method) } if v.any? { |value| value.class == Hash }
-
end
-
24
support[k.public_send(conversion_method)] = con || v
-
end
-
13
support
-
end
-
-
# Get the diff of the current resource state and the desired state
-
# @param [OneviewSDK::Resource] resource Resource containing current state
-
# @param [Hash] desired_data Desired state for the resource
-
# @return [String] Diff string (multi-line). Returns empty string if there is no diff or an error occurred
-
1
def self.get_diff(resource, desired_data)
-
3
data = resource.is_a?(Hash) ? resource : resource.data
-
3
recursive_diff(data, desired_data, '', ' ')
-
rescue StandardError => e
-
1
Chef::Log.error "Failed to generate resource diff for '#{resource['name']}': #{e.message}"
-
1
'' # Return empty diff
-
end
-
-
# Get the diff of the current resource state and the desired state
-
# @param [Hash] data Current state of the resource
-
# @param [Hash] desired_data Desired state for the resource
-
# @param [String] str Current diff string to append to (used for recursive calls)
-
# @param [String] indent String used to indent the output
-
# @raise [StandardError] if the comparison cannot be made due to an unexpected error
-
# @return [String] Diff string (multi-line). Returns empty string if there is no diff
-
1
def self.recursive_diff(data, desired_data, str = '', indent = '')
-
22
unless desired_data.class == Hash
-
10
return '' if data == desired_data
-
8
return str << "\n#{indent}#{data.nil? ? 'nil' : data} -> #{desired_data}"
-
end
-
12
return str << "\n#{indent}nil -> #{desired_data}" if data.nil?
-
11
return str << "\n#{indent}#{data} -> #{desired_data}" unless data && data.class == Hash
-
11
desired_data.each do |key, val|
-
22
if val.is_a?(Hash)
-
5
if data[key].class == Hash
-
3
str2 = recursive_diff(data[key], val, '', "#{indent} ")
-
3
str << "\n#{indent}#{key}:#{str2}" unless str2.empty?
-
else
-
2
str << "\n#{indent}#{key}: #{data[key].nil? ? 'nil' : data[key]} -> #{val}"
-
end
-
17
elsif val != data[key]
-
8
str << "\n#{indent}#{key}: #{data[key].nil? ? 'nil' : data[key]} -> #{val}"
-
end
-
end
-
11
str
-
end
-
-
# Retrieve a resource by type and identifier (name or data)
-
# @param [Hash, OneviewSDK::Client] client Appliance info hash or client object.
-
# @param type [String, Symbol] Type of resource to be retrieved. e.g., :GoldenImage, :FCNetwork
-
# @param id [String, Symbol, Hash] Name of the resource or Hash of data to retrieve by.
-
# Examples: 'EthNet1', { uri: '/rest/fake/123ABC' }
-
# @param ret_attribute [NilClass, String, Symbol] If specified, returns a specific attribute of the resource.
-
# When nil, the complete resource will be returned.
-
# @param api_ver [Integer] API version used to build the full type namespace.
-
# Defaults to 200 (unless node attribute is passed)
-
# @param variant [String, Symbol] API variant used to build the full type namespace.
-
# Defaults to 'C7000' (unless node attribute is passed)
-
# @param node [Chef::Node] Node object used to provide the api_ver and variant. If provided, they will default
-
# to node['oneview']['api_version'] and node['oneview']['api_variant']
-
# @return [OneviewSDK::Resource] if the `ret_attribute` is nil
-
# @return [String, Array, Hash] that is, the value of the resource attribute defined by `ret_attribute`
-
# @raise [OneviewSDK::NotFound] ResourceNotFound if the resource cannot be found
-
# @raise [OneviewSDK::IncompleteResource] If you don't specify any unique identifiers in `id`
-
1
def self.load_resource(client, type: nil, id: nil, ret_attribute: nil, api_ver: nil, variant: nil, node: nil, base_module: OneviewSDK)
-
14
raise(ArgumentError, 'Must specify a resource type') unless type
-
13
return unless id
-
12
c = build_client(client)
-
12
api_ver ||= node['oneview']['api_version'] rescue 200
-
12
variant ||= node['oneview']['api_variant'] rescue 'C7000'
-
12
klass = base_module.resource_named(type, api_ver, variant)
-
12
data = id.is_a?(Hash) ? id : { name: id }
-
12
r = klass.new(c, data)
-
12
raise(OneviewSDK::NotFound, "#{type} with data '#{data}' was not found") unless r.retrieve!
-
10
return r unless ret_attribute
-
2
r[ret_attribute]
-
end
-
end
-
end
-
-
1
require_relative 'resource_provider'
-
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
-
#
-
# Licensed under the Apache License, Version 2.0 (the "License");
-
# you may not use this file except in compliance with the License.
-
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-
#
-
# Unless required by applicable law or agreed to in writing, software distributed
-
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
-
# specific language governing permissions and limitations under the License.
-
-
1
module OneviewCookbook
-
# Define default properties for all resources
-
1
module ResourceBaseProperties
-
# Loads the default properties for all resources
-
1
def self.load(context)
-
10
context.property :client
-
10
context.property :name, [String, Symbol], required: true
-
10
context.property :data, Hash, default: {}
-
10
context.property :save_resource_info, [TrueClass, FalseClass, Array], default: safe_dup(context.node['oneview']['save_resource_info'])
-
10
context.property :api_version, Integer, default: safe_dup(context.node['oneview']['api_version'])
-
10
context.property :api_variant, [String, Symbol], default: safe_dup(context.node['oneview']['api_variant'])
-
10
context.property :api_header_version, Integer # Overrides X-API-Version headers in API requests
-
10
context.property :operation, String # To be used with :patch action
-
10
context.property :path, String # To be used with :patch action
-
10
context.property :value, [String, Array] # To be used with :patch action
-
end
-
-
1
def self.safe_dup(object)
-
32
object.dup
-
rescue TypeError
-
object
-
end
-
end
-
end
-
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
-
#
-
# Licensed under the Apache License, Version 2.0 (the "License");
-
# you may not use this file except in compliance with the License.
-
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-
#
-
# Unless required by applicable law or agreed to in writing, software distributed
-
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
-
# specific language governing permissions and limitations under the License.
-
-
1
module OneviewCookbook
-
# Base class for resource providers
-
1
class ResourceProvider
-
1
attr_accessor \
-
:context, # Ususally a Chef resource's context (self)
-
:resource_name, # The Chef resource's type. e.g., oneview_ethernet_network
-
:name, # Name of the Chef resource. e.g., EthNet1
-
:item, # The OneviewSDK resource instance
-
:sdk_api_version, # Keep track of the API version used for the SDK resource class
-
:sdk_variant, # Keep track of the variant used for the SDK resource class
-
:sdk_resource_type, # Keep track of the SDK resource class name
-
:sdk_base_module # Keep track of the internal base SDK module
-
-
1
def initialize(context)
-
67
@sdk_base_module = OneviewSDK
-
67
@context = context
-
67
@new_resource = context.new_resource
-
67
@resource_name = context.new_resource.resource_name
-
67
@name = context.new_resource.name
-
67
klass = parse_namespace
-
66
c = if @sdk_base_module == OneviewSDK::ImageStreamer
-
4
OneviewCookbook::Helper.build_image_streamer_client(@new_resource.client)
-
else
-
62
OneviewCookbook::Helper.build_client(@new_resource.client)
-
end
-
66
new_data = JSON.parse(@new_resource.data.to_json) rescue @new_resource.data
-
66
@item = context.property_is_set?(:api_header_version) ? klass.new(c, new_data, @new_resource.api_header_version) : klass.new(c, new_data)
-
66
@item['name'] ||= @new_resource.name
-
end
-
-
# rubocop:disable Metrics/MethodLength
-
# Helper method that analyzes the namespace and defines the class variables and the resource class itself
-
# @return [OneviewSDK::Resource] SDK resource class
-
# @raise [NameError] If for some reason the method could not resolve the namespace to a OneviewSDK::Resource
-
1
def parse_namespace
-
67
klass_name = self.class.to_s
-
67
Chef::Log.debug("Resource '#{@resource_name}' received with the '#{klass_name}' class name")
-
67
name_arr = klass_name.split('::')
-
67
@sdk_resource_type = name_arr.pop.gsub(/Provider$/i, '') # e.g., EthernetNetwork
-
67
case name_arr.size
-
when 1
-
44
Chef::Log.debug("Resource '#{klass_name}' has no variant or api version specified.")
-
# This case should really only be used for testing
-
# Uses the SDK's default api version and variant
-
44
return OneviewSDK.resource_named(@sdk_resource_type)
-
when 2 # No variant specified. e.g., OneviewCookbook::API200::EthernetNetworkProvider
-
6
Chef::Log.debug("Resource '#{klass_name}' has no variant specified.")
-
6
@sdk_api_version = name_arr.pop.gsub(/API/i, '').to_i # e.g., 200
-
6
@sdk_variant = nil # Not needed
-
when 3
-
# Parses all the namespace when it is fully specified with API version, variant or base module
-
16
case klass_name
-
when /ImageStreamer/
-
4
Chef::Log.debug("Resource '#{klass_name}' is a Image Streamer resource.")
-
4
@sdk_api_version = name_arr.pop.gsub(/API/i, '').to_i # e.g., 300
-
4
@sdk_base_module = OneviewSDK.const_get(name_arr.pop) # ImageStreamer
-
4
@sdk_variant = nil # Not needed
-
else # The variant is specified. e.g., OneviewCookbook::API200::C7000::EthernetNetworkProvider
-
12
Chef::Log.debug("Resource '#{klass_name}' has variant and api version specified.")
-
12
@sdk_variant = name_arr.pop # e.g., C7000
-
12
@sdk_api_version = name_arr.pop.gsub(/API/i, '').to_i # e.g., 200
-
end
-
else # Something is wrong
-
1
raise NameError, "Can't build a resource object from the class #{self.class}"
-
end
-
22
klass = @sdk_base_module.resource_named(@sdk_resource_type, @sdk_api_version, @sdk_variant)
-
22
Chef::Log.debug("#{@resource_name} namespace parsed:
-
> SDK Base Module: #{@sdk_base_module} <#{@sdk_base_module.class}>
-
> SDK API Version: #{@sdk_api_version} <#{@sdk_api_version.class}>
-
> SDK Variant: #{@sdk_variant} <#{@sdk_variant.class}>
-
> SDK Resource Type: #{@sdk_resource_type} <#{@sdk_resource_type.class}>
-
")
-
22
klass
-
end
-
# rubocop:enable Metrics/MethodLength
-
-
# Creates the OneView resource or updates it if exists
-
# @param [Symbol] method_1 Method used to create/add
-
# @param [Symbol] method_2 Method used to update/edit
-
# @return [TrueClass, FalseClass] Returns true if the resource was created, false if updated or unchanged
-
1
def create_or_update(method_1 = :create, method_2 = :update)
-
4
ret_val = false
-
4
desired_state = Marshal.load(Marshal.dump(@item.data))
-
4
if @item.exists?
-
2
@item.retrieve!
-
2
if @item.like? desired_state
-
1
Chef::Log.info("#{@resource_name} '#{@name}' is up to date")
-
else
-
1
diff = get_diff(@item, desired_state)
-
1
Chef::Log.info "#{method_2.to_s.capitalize} #{@resource_name} '#{@name}'#{diff}"
-
1
Chef::Log.debug "#{@resource_name} '#{@name}' Chef resource differs from OneView resource."
-
1
Chef::Log.debug "Current state: #{JSON.pretty_generate(@item.data)}"
-
1
Chef::Log.debug "Desired state: #{JSON.pretty_generate(desired_state)}"
-
1
@context.converge_by "#{method_2.to_s.capitalize} #{@resource_name} '#{@name}'" do
-
1
@item.update(desired_state)
-
end
-
end
-
else
-
2
create(method_1)
-
2
ret_val = true
-
end
-
4
save_res_info
-
4
ret_val
-
end
-
-
# Adds the resource to OneView or edits it if exists
-
# @return [TrueClass, FalseClass] Returns true if the resource was added, false if edited or unchanged
-
1
def add_or_edit
-
1
create_or_update(:add, :edit)
-
end
-
-
# Creates the OneView resource only if it doesn't exist
-
# @param [Symbol] method Create or add method
-
# @return [TrueClass, FalseClass] Returns true if the resource was created/added
-
1
def create_if_missing(method = :create)
-
4
ret_val = false
-
4
if @item.exists?
-
2
Chef::Log.info("#{@resource_name} '#{@name}' exists. Skipping")
-
2
@item.retrieve! if @new_resource.save_resource_info
-
else
-
2
create(method)
-
2
ret_val = true
-
end
-
4
save_res_info
-
4
ret_val
-
end
-
-
# Adds a resource to OneView only if it doesn't exist
-
# @return [TrueClass, FalseClass] Returns true if the resource was added
-
1
def add_if_missing
-
1
create_if_missing(:add)
-
end
-
-
# Delete the OneView resource if it exists
-
# @param [Symbol] method Delete or remove method
-
# @return [TrueClass, FalseClass] Returns true if the resource was deleted/removed
-
1
def delete(method = :delete)
-
2
return false unless @item.retrieve!
-
1
@context.converge_by "#{method.to_s.capitalize} #{@resource_name} '#{@name}'" do
-
1
@item.send(method)
-
end
-
1
true
-
end
-
-
# Remove the OneView resource if it exists
-
# @return [TrueClass, FalseClass] Returns true if the resource was removed
-
1
def remove
-
1
delete(:remove)
-
end
-
-
# Performs patch operation
-
# It needs the context properties 'operation' and 'path'.
-
# 'value' property is optional.
-
# @return [TrueClass] true if the resource was patched
-
1
def patch
-
5
invalid_params = @new_resource.operation.nil? || @new_resource.path.nil?
-
5
raise "InvalidParameters: Parameters 'operation' and 'path' must be set for patch" if invalid_params
-
3
raise "ResourceNotFound: Patch failed to apply since #{@resource_name} '#{@name}' does not exist" unless @item.retrieve!
-
2
@context.converge_by "Performing '#{@new_resource.operation}' at #{@new_resource.path} with #{@new_resource.value} in #{@resource_name} '#{@name}'" do
-
2
@item.patch(@new_resource.operation, @new_resource.path, @new_resource.value)
-
end
-
2
true
-
end
-
-
# This method is shared between multiple actions and takes care of the creation of the resource.
-
# Only call this method if the resource does not exist and needs to be created.
-
# @param [Symbol] method Create method
-
1
def create(method = :create)
-
4
Chef::Log.info "#{method.to_s.capitalize} #{@resource_name} '#{@name}'"
-
4
@context.converge_by "#{method.to_s.capitalize} #{@resource_name} '#{@name}'" do
-
4
@item.send(method)
-
end
-
end
-
-
# Adds scopes to the Oneview resource if scope is not already added
-
1
def add_to_scopes
-
9
apply_scopes_action(:add_to_scopes, :add_scope) { |scope| @item['scopeUris'].include?(scope['uri']) }
-
end
-
-
# Removes scopes from the Oneview resource if scope is already added
-
1
def remove_from_scopes
-
9
apply_scopes_action(:remove_from_scopes, :remove_scope) { |scope| !@item['scopeUris'].include?(scope['uri']) }
-
end
-
-
# Helper method to apply method related to add or remove scopes in Oneview resource
-
1
def apply_scopes_action(action, resource_method, &ignore_scope_if)
-
6
return Chef::Log.info("No scopes were specified to perform #{action}. Skipping") if @new_resource.scopes.nil? || @new_resource.scopes.empty?
-
6
raise "ResourceNotFound: #{@resource_name} '#{@name}' does not exist" unless @item.retrieve!
-
18
scopes = @new_resource.scopes.map { |scope_name| load_resource(:Scope, scope_name) }
-
6
scopes.delete_if(&ignore_scope_if)
-
6
return Chef::Log.info("'#{action}' with '#{@new_resource.scopes}' to #{@resource_name} '#{@name}' is not needed. Skipping") if scopes.empty?
-
10
scope_names = scopes.map { |scope| scope['name'] }.sort
-
4
@context.converge_by "Performing #{action} '#{scope_names}' in #{@resource_name} '#{@name}'" do
-
4
scopes.each do |scope|
-
6
@item.send(resource_method, scope)
-
end
-
end
-
end
-
-
# Replaces scopes to the Oneview resource
-
1
def replace_scopes
-
3
return Chef::Log.info('No scopes were specified to perform replace_scopes. Skipping') if @new_resource.scopes.nil?
-
3
raise "ResourceNotFound: #{@resource_name} '#{@name}' does not exist" unless @item.retrieve!
-
9
scopes = @new_resource.scopes.map { |scope_name| load_resource(:Scope, scope_name) }
-
9
scope_uris = scopes.map { |scope| scope['uri'] }
-
3
if @item['scopeUris'].sort == scope_uris.sort
-
1
return Chef::Log.info("Scopes '#{@new_resource.scopes}' already are scopes of #{@resource_name} '#{@name}'. Skipping")
-
end
-
2
@context.converge_by "Replaced Scopes '#{@new_resource.scopes.sort}' for #{@resource_name} '#{@name}'" do
-
2
@item.replace_scopes(scopes)
-
end
-
end
-
-
# Gathers the OneviewSDK correct resource class
-
# @param [Symbol, String] resource Resource name/type desired
-
# @param [Integer] version Version of the SDK desired
-
# @param [String] variant Variant of the SDK desired
-
# @return [OneviewSDK::Resource] Returns the class of the resource in the loaded API version and variant
-
1
def resource_named(resource, version = @sdk_api_version, variant = @sdk_variant)
-
3
@sdk_base_module.resource_named(resource, version, variant)
-
end
-
-
# Save the data from a resource to a node attribute
-
# @param [TrueClass, FalseClass, Array] attributes Attributes to save (or true/false)
-
# @param [String, Symbol] name Resource name
-
# @param [OneviewSDK::Resource] item to save data for
-
# (@new_resource.save_resource_info, @name, @item)
-
1
def save_res_info
-
4
ov_url = @item.client.url.to_s
-
4
case @new_resource.save_resource_info
-
when Array # save subset
-
5
@context.node.default['oneview'][ov_url][@name.to_s] = @item.data.select { |k, _v| @new_resource.save_resource_info.include?(k) }
-
when TrueClass # save all
-
1
@context.node.default['oneview'][ov_url][@name.to_s] = @item.data
-
end
-
rescue StandardError => e
-
1
Chef::Log.error "Failed to save resource data for '#{@name}': #{e.message}"
-
end
-
-
# Utility method that converts Hash symbol to string keys
-
# See the OneviewCookbook::Helper.convert_keys method for param details
-
1
def convert_keys(info, conversion_method)
-
1
OneviewCookbook::Helper.convert_keys(info, conversion_method)
-
end
-
-
# Get the diff of the current resource state and the desired state
-
# See the OneviewCookbook::Helper.get_diff method for param details
-
1
def get_diff(resource, desired_data)
-
2
diff = OneviewCookbook::Helper.get_diff(resource, desired_data)
-
2
return '. (no diff)' if diff.to_s.empty?
-
1
". Diff: #{diff}"
-
end
-
-
# Get the diff of the current resource state and the desired state
-
# See the OneviewCookbook::Helper.recursive_diff method for param details
-
1
def recursive_diff(data, desired_data, str = '', indent = '')
-
2
OneviewCookbook::Helper.recursive_diff(data, desired_data, str, indent)
-
end
-
-
# Retrieve a resource by type and identifier (name or data)
-
# See the OneviewCookbook::Helper.load_resource method for param details
-
1
def load_resource(resource_class_type, resource_id, ret_attribute = nil)
-
5
OneviewCookbook::Helper.load_resource(
-
@item.client,
-
type: resource_class_type,
-
id: resource_id,
-
ret_attribute: ret_attribute,
-
api_ver: @sdk_api_version,
-
variant: @sdk_variant,
-
base_module: @sdk_base_module
-
)
-
end
-
-
# Validates the presence of resource properties
-
# @param [Symbol] property An property name to be validating presence
-
# @param [Symbol] ... More property names
-
# @raise [RuntimeError] if some property is not set
-
1
def validate_required_properties(*properties)
-
6
properties.each { |property| raise("Unspecified property: '#{property}'. Please set it before attempting this action.") unless @new_resource.public_send(property) }
-
end
-
end
-
end
-
-
# Load all resource providers:
-
9
Dir[File.dirname(__FILE__) + '/resource_providers/*.rb'].each { |file| require file }