Search code examples
rubyibm-cloud-infrastructure

Ruby SoftLayer API call SoftLayer_Billing_Invoice::getItems returns a hostName value that has been downcased


I'm running a program to retrieve my latest recurring invoice and then I want to look through each item in the invoice and get a list of hostnames. Here is it in a simplified form:

account = SoftLayer::Service.new("SoftLayer_Account",:username => user, :api_key => api_key, :timeout => 999999999)

softlayer_client = SoftLayer::Client.new(:username => user, :api_key => api_key)

billing_invoice_service = softlayer_client.service_named("Billing_Invoice")

object_filter = SoftLayer::ObjectFilter.new
object_filter.set_criteria_for_key_path('invoices.createDate', 'operation' => 'betweenDate', 'options' => [{'name' => 'startDate', 'value' => ["01/01/2016"]}, {'name' => 'endDate', 'value' => ["01/02/2016"]}])

invoices = account.result_limit(0,10000).object_filter(object_filter).object_mask("mask[id,typeCode,itemCount,invoiceTotalAmount,closedDate,createDate]").getInvoices

invoices.each do | invoice |
  if invoice["typeCode"] == "RECURRING"
    invoice_reference = billing_invoice_service.object_with_id(invoice["id"])
    invoice_object = invoice_reference.object_mask("mask[itemCount]").getObject
    billing_items_count = invoice_object["itemCount"]

    for i in 0..(billing_items_count/10000.0).ceil - 1
      billing_items = invoice_reference.result_limit(i*10000, 10000).object_mask("mask[id,hostName]").getItems()
      billing_items.each do | billing_item |
        if billing_item["hostName"]
          pp billing_item
        end
      end
    end
  end
end

Here is the corresponding link to the documentation: http://sldn.softlayer.com/reference/services/SoftLayer_Billing_Invoice/getItems

The result is a list of hostnames but the values have been downcased. This is blocking me as I later make a find_servers call and pass this 'hostName' value from above. It fails to find the server details because the case does not match. I've run a test like below to confirm this behavior:

softlayer_client = SoftLayer::Client.new(:username => user, :api_key => api_key)

found_downcased_version = SoftLayer::VirtualServer.find_servers({ :client => softlayer_client, :hostname => "host-hadr-1" })

if !found_downcased_version.empty?
  pp "FOUND DOWNCASED VERSION OF HOSTNAME"
end

found_unchanged_case_version = SoftLayer::VirtualServer.find_servers({ :client => softlayer_client, :hostname => "host-HADR-1" })

if !found_unchanged_case_version.empty?
  pp "FOUND UNCHANGED CASE VERSION OF HOSTNAME"
end

This seems like an issue that SoftLayer will return a result where it has changed the case of the hostname.

1) Is there a way to make my find_servers call case-insensitive?

or

2) Is there a way to get the virtual_guest/hardware ID out of the invoice? So that instead of using find_server with the hostname argument, I could use server_with_id potentially.

Thank you!


Solution

  • The method getItems returns an array of SoftLayer_Billing_Invoice_Item, this object has the property billingItemId (see http://sldn.softlayer.com/reference/datatypes/SoftLayer_Billing_Invoice_Item) which is the billing item from which this invoice item was generated. Now that billingItemId must match with the associated billingItemId either a Server or VSI in your account. So you can find either your server or VSI using the billingItemId

    take a look at this code:

    # To get the VSI
    billingItemId = invoiceItem["billingItemId"]
    account_service = softlayer_client.service_named("Account")
    filter = SoftLayer::ObjectFilter.new {|f| f.accept("virtualGuests.billingItem.id").when_it is(billingItemId)}
    # The method returns an array of VSIs, but because the filter the arrays should contain only one VSI
    vsis = account_service.object_filter(filter).getVirtualGuests()
    myVSI = vsi[0]
    
    
    # To get the Server
    billingItemId = invoiceItem["billingItemId"]
    filter = SoftLayer::ObjectFilter.new {|f| f.accept("hardware.billingItem.id").when_it is(billingItemId)}
    hardwares = account_service.object_filter(filter).getHardware()
    myHardware = hardwares[0]
    

    I hope it helps