You now have the ability to add “Embedded Methods” in each of your Ruby method. Above the code area, you have a button named “Add Method”. It allows you to insert the code of a method just before yours, in a “require” approach. I have started using it lately to factor code for better reusability.
You import a method, not a class, so it might feel strange in the object oriented approach. In my case, I use methods called “Utils” for each area I need to factor. I also use the new method syntax based on modules and classes: https://github.com/ManageIQ/manageiq-content/issues/8.
Here is an example. I need to do some actions on a RHV/oVirt VM, but it is not (yet) available in the provider. I have created a utility class (which simply calls a method) with a method called Utils. The code is in /FabienDupont/Providers/RedHat/Utils
with the following code:
module FabienDupont
module Providers
module RedHat
class Utils
def initialize(handle = $evm)
@debug = true
@handle = handle
end
def main
end
def rhv_rest(ems, method, request, payload="")
require 'restclient'
require 'json'
# Set default content type to JSON
accept = 'application/json'
content_type = 'application/json'
# Override content type if payload contains XML
if [:post, :put].include?(method) and /^</.match(payload)
accept = 'application/xml'
content_type = 'application/xml'
end
@handle.log(:info, "Connecting to RHV Manager: #{ems.hostname} as #{ems.authentication_userid}.") if @debug
response = RestClient::Request.new(
:method => method,
:url => "https://#{ems.hostname}/#{request.gsub(/^\//, '')}",
:user => ems.authentication_userid,
:password => ems.authentication_password,
:verify_ssl => false,
:payload => payload,
:headers => {
:accept => accept,
:content_type => content_type
}
).execute
result = method.to_s.match('get') ? JSON.parse(response) : response
return result
end
def vm_update_description(vm, description)
payload = "<vm><description>#{description}</description></vm>"
self.rhv_rest(vm.ext_management_system, :put, vm.ems_ref_string, payload)
end
end
end
end
end
if __FILE__ == $PROGRAM_NAME
FabienDupont::Providers::RedHat::VM_UpdateDescription.new.main
end
The code itself is quite simple: it calls the RHV/oVirt API in the rhv_rest
method which is used by the vm_update_description
that basically updates the VM description in RHV/oVirt (captain obvious’s not far
). With that, I can have a very simple method later on, to update the description of my VM, for example as a post provision task in the provisioning state machine. To do so, I have created a method named VM_UpdateDescription
in my utility class, and this method leverages the Utils
method:
module FabienDupont
module Providers
module RedHat
class VM_UpdateDescription
def initialize(handle = $evm)
@debug = true
@handle = handle
end
def main
vm = @handle.root['target_vm']
description = "Provisioned by Cloudforms on #{Time.now}."
FabienDupont::Providers::RedHat::Utils.new.vm_update_description(vm, description)
end
end
end
end
end
if __FILE__ == $PROGRAM_NAME
FabienDupont::Providers::RedHat::VM_UpdateDescription.new.main
end
In the VM_UpdateDescription
, I have added the /FabienDupont/Providers/RedHat/Utils
method as an Embedded Method, so I can call it using FabienDupont::Providers::RedHat::Utils.new.vm_update_description(vm, description)
. If I used it more than one time, I could instantiate a reusable object by simply doing the following:
def initialize(handle = $evm)
@debug = true
@handle = handle
@rhv_utils= FabienDupont::Providers::RedHat::Utils.new
end
def main
vm = @handle.root['target_vm']
description = "Provisioned by Cloudforms on #{Time.now}."
@rhv_utils.vm_update_description(vm, description)
end
This is not exactly gem-ish, but it allows creating a library of reusable code. Another advantage upon Gem is that the code is stored in the Automate tree, thus in the database, so it is available to all appliances of the region without installing Gem.