Ruby : SoftLayer API : getPendingEvents fails to show many relational properties - ruby

I'm trying to make a softlayer API call using Ruby to see upcoming maintenance and the machines that may be effected by the maintenance. I have a few questions but I'm running into an issue seeing many of the relational properties documented here:
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Notification_Occurrence_Event
Here is my simple program:
require 'rubygems'
require 'softlayer_api'
require 'pp'
client = SoftLayer::Client.new(:username => user, :api_key => api_key, :timeout => 99999999)
account = client['Account'].object_mask("mask[pendingEventCount]").getObject()
pending_event_count = account["pendingEventCount"]
current_time = Time.now.to_i
for i in 0..(pending_event_count/30.0).ceil - 1
list_of_pending_events = client['Account'].result_limit(i*30,30).object_mask("mask[id, startDate, endDate, recoveryTime, subject, summary]").getPendingEvents
for x in 0..list_of_pending_events.length - 1
start_time = DateTime.parse(list_of_pending_events[x]['startDate']).to_time.to_i
if start_time > current_time
pp list_of_pending_events[x]
end
end
end
The above works, but if I try to add a relational property to the mask, such as "impactedResources" it will fail saying that property does not belong to SoftLayer_Notification_Occurrence_Event. Can someone help explain why this, and many other, relational properties are not valid in the above call?
Also, two quick other questions on this topic:
1) Why do some of the results in getPendingEvents have start AND end times in the past? And why do some have a missing end time altogether? Notice I'm checking if the start time is greater than the current time as there seems to be old maintenance data in the results.
2) Am I taking the right approach for getting upcoming maintenance and figuring out machines that will be impacted? (Using getPendingEvents and then the 'impactedResources' property)

I used your code and I added the "impactedResources" to the object mask and it worked fine. You may be getting the issue, because your API user does not have enough permissions, I recomend you try with the master user.
regarding to your other questions:
1.- When I ran your code I got only 3 events whose startDate is greater than the current time, so it worked fine for me. If you still are getting that issue you can try using objectFilters.
require 'rubygems'
require 'softlayer_api'
require 'pp'
client = SoftLayer::Client.new(:username => user, :api_key => apikey, :timeout => 99999999)
object_filter = SoftLayer::ObjectFilter.new
object_filter.set_criteria_for_key_path('pendingEvents.startDate', 'operation' => 'greaterThanDate',
'options' => [{
'name' => 'date',
'value' => ['9/8/2016']
}])
list_of_pending_events = client['Account'].object_filter(object_filter).object_mask("mask[id, startDate, endDate, recoveryTime, subject, summary]").getPendingEvents
pp list_of_pending_events
2.- Yes, that approach wil work.
Regards

Related

Google ad manager try to read revenue per hour fails on ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS

I have a simple script that fetch data from google ad manager.
Everything is working pretty fine, Now I am trying to read the same data but instead of date aggregation, I am trying by day and hour.
I get the following error:
AdManagerApi::V201905::ReportService::ApiException: [ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS # columns; trigger:'TOTAL_LINE_ITEM_LEVEL_CPM_AND_CPC_REVENUE']
My report query in ruby is:
# Create report query.
report_query = {
:date_range_type => 'CUSTOM_DATE',
:start_date => AdManagerApi::AdManagerDate.new(#ad_manager, start_date).to_h,
:end_date => AdManagerApi::AdManagerDate.new(#ad_manager, end_date).to_h,
:dimensions => ['DAY', 'HOUR', 'CUSTOM_CRITERIA'],
:columns => ['TOTAL_LINE_ITEM_LEVEL_CPM_AND_CPC_REVENUE']
}
I took the full example from here
I am pretty new with the google ad manager api, I will appreciate any suggestion.
Try removing CUSTOM_CRITERIA from the :dimensions list

How to access data within variable? Error: undefined method

Printing the contents of a variable gives me a bunch of data.
I want to access part of that data, but get an error.
I'm using Viewpoint::EWS and am successfully accessing the data I need.
calendaritems = folder.find_items({:folder_id => folder.folder_id, :calendar_view => {:start_date => sd.rfc3339(), :end_date => ed.rfc3339()}})
calendaritems.each do |event|
...
end
Printing the variable "event", I can see the data I need: "date_time_stamp" (or "appointment_reply_time").
#<Viewpoint::EWS::Types::CalendarItem:0x00005652b332dfa0
#ews_item=
:date_time_stamp=>{:text=>"2019-03-18T12:01:49Z"},
:appointment_reply_time=>{:text=>"2019-03-18T13:01:55+01:00"},
However, trying to access using "event.date_time_stamp" (or "event.appointment_reply_time") leads to the error
undefined method `date_time_stamp' for <Viewpoint::EWS::Types::CalendarItem:0x00005622f83c3d38> (NoMethodError)
Here's the code:
calendaritems = folder.find_items({:folder_id => folder.folder_id, :calendar_view => {:start_date => sd.rfc3339(), :end_date => ed.rfc3339()}})
calendaritems.each do |event|
if event.recurring?
puts "#{event.date_time_stamp} | #{(event.start-event.date_time_stamp).to_i} | #{event.organizer.email_address}"
if (event.start-event.date_time_stamp).to_i == reminderDays
executeSomething()
end
end
end
I'm looking through recurring appointments for a resource within a week. Since those will be silently dropped after a year, the plan is to set up a system to remind people that this will happen, so they can rebook the resource.
At first I tried using the creation date of the appointment (event.date_time_created), which works as expected, but then noticed, that people can update their appointments, thus resetting the 1 year timer.
That's why I also need the date of the last update.
The debug output you supplied says that event variable has an attribute "ews_item" and then it has a hash with an attribute "date_time_stamp", so try event.ews_item[:date_time_stamp]

ruby, postgres ,compare data from two tables coming from two databases

we have a database legacy from a SQL SERVER, and now the new database is a postgres, I would like to do some testing to see if the content is the same from both tables, sinnce I still don't have acess to the legacy database (SQL server), I said let play with the new postgres database by polling two table and try to compare the data, in the iteration loop I got confused, any idea will be helpful :
require 'pg'
pg_conn = PGconn.connect("localhost", 5432, '', '', "myDB", "userxx", "Zazzz")
all_children = pg_conn.exec("SELECT * from COMPANY;")
all_children2 = pg_conn.exec("SELECT * from COMPANY2;")
all_children.each do |child|
??????
end
Thanks,
The quick and dirty way would be to do a fast checking on one column, for example the name of the companies and compare the results to see the differences by substracting the resulting arrays :
require 'pg'
pg_conn = PGconn.connect("localhost", 5432, '', '', "myDB", "userxx", "Zazzz")
all_children = pg_conn.exec("SELECT name from COMPANY;")
all_children2 = pg_conn.exec("SELECT name from COMPANY2;")
# first check the count, if it's the same it's probably a good sign
puts all_children.length
puts all_children2.length
# check differences
results = all_children.uniq - all_children2.uniq
results2 = all_children2.uniq - all_children.uniq
For more complex tests you can maybe use the scientist gem from github : https://github.com/github/scientist
Edit:
sql version ?
select * from company left outer join company2 on company.name = company.name2 where company2.name is null;

Get all open pull requests from an organisation using the Github API Ruby gem

For our organisation's dashboard, I'd like to keep a count of all the open PRs on all our repositories. At the moment, all I've got is to loop through all the repos, and count through all the open PRs on each repo like so (which often results in a rate limit error):
connection = Github.new oauth_token: MY_OAUTH_TOKEN
pulls = 0
connection.repos.list(:org => GITHUB_ORGANISATION).each do |repo|
pulls += connection.pull_requests.list(:user => repo['owner']['login'], :repo => repo['name']).count
end
I know there must be a nicer way round this. Any ideas? (short of screen scraping!)
OK, so I think I've cracked this now. Pull requests are issues, so I can get all issues, and loop through the issues like so:
pulls = 0
issues = connection.issues.list(:org => GITHUB_ORGANISATION, :filter => 'all', :auto_pagination => true)
issues.each do |issue|
if issue["pull_request"]
pulls += 1
end
end
Once you remember that pull requests are issues too, everything just falls into place.

Enumerating settable parameters

I successfully setup a connection to my Rally project, but am not able to programatically set the "Submitted By" field when opening defects. I am misnaming the parameter, or it is not settable via the REST API. Any help on querying modifiable parameters, link to attribute names, or code to set the "Submitted By" parameter would be greatly appreciated.
My goal is to have a webpage where folks submit defects or stories, along with their email, and use that to populate their username in the "Submitted By" field. My current setup can open Stories and Defects but only anonymously since the second to last line has no effect.
I am using the Ruby API and the following is the ruby code that gets invoked when a user clicks on a button on the main page, which redirects them to localhost:4567/rally_defect where Sinatra is listening.
require 'rubygems'
require 'rally_rest_api'
require 'sinatra'
custom_headers = CustomHttpHeader.new
custom_headers.name = 'Mail 2 Rally'
custom_headers.version = '0.1'
custom_headers.vendor = 'Rally Software'
rally_server = 'https://rally1.rallydev.com/slm'
rally_username = <insert rally username>
rally_pwd = <insert rally password>
rally = RallyRestAPI.new(:base_url => rally_server,
:username => rally_username,
:password => rally_pwd,
:http_headers => custom_headers)
get '/rally_defect' do
rally.create(:defect, :name => "Test Defect",
:description => "This is a test",
:SubmittedBy => "test")
end
If you're getting started building this integration, I'd strongly recommend using rally_api instead of rally_rest_api.
rally_rest_api is in the process of being deprecated for a number of issues around performance and stability. There won't be any further development on rally_rest_api moving forward.
You can find documentation on rally_api here:
https://developer.help.rallydev.com/ruby-toolkit-rally-rest-api-json
rally_api does require Ruby 1.9.2 or higher.
rally_api's syntax is quite similar to rally_rest_api. The rally_api version of what you're attempting above would look something like the code sample below. Note that any "set-able" parameter can be set simply by including its name in the object hash and setting that to a value.
The best place to look for the Rally Webservices API object model, including Artifact attributes, allowed values, and whether they are write-able is the Webservices API documentation:
https://rally1.rallydev.com/slm/doc/webservice
When an attribute of a Rally Artifact is itself a Rally Object like a User, for example, either lookup the Object in Rally first (the example below does this), or, set the value to the REST URL reference to the object in Rally. For instance, if you know that user#company.com has ObjectID 12345678910 in Rally, then you can do:
user_ref = "/user/12345678910"
new_defect["SubmittedBy"] = user_ref
The code below shows the way to do a lookup into Rally to get the User object, given an email-formatted UserID, since I'm assuming you'll probably need to accomodate multiple different users.
require 'rubygems'
require 'rally_api'
require 'sinatra'
#Setting custom headers
headers = RallyAPI::CustomHttpHeader.new()
headers.name = 'Mail 2 Rally'
headers.vendor = "My Company"
headers.version = "0.1"
# Rally credentials
rally_username = <insert rally username>
rally_pwd = <insert rally password>
rally_server = 'https://rally1.rallydev.com/slm'
# Rally REST API config
config = {:base_url => rally_server}
config[:username] = rally_username
config[:password] = rally_pwd
config[:workspace] = "Workspace Name"
config[:project] = "Project Name"
config[:headers] = headers #from RallyAPI::CustomHttpHeader.new()
# New up rally connection config
#rally = RallyAPI::RallyRestJson.new(config)
# Lookup UserID for SubmittedBY
submitted_by_user_id = "user#company.com"
user_query = RallyAPI::RallyQuery.new()
user_query.type = :user
user_query.fetch = "ObjectID,UserName,DisplayName"
user_query.order = "UserName Asc"
user_query.query_string = "(UserName = \"#{submitted_by_user_id}\")"
# Query for user
user_query_results = #rally.find(user_query)
submitted_by_user = user_query_results.first
# Create the Defect
new_defect = {}
new_defect["Name"] = "Test Defect"
new_defect["Description"] = "This is a test"
new_defect["SubmittedBy"] = submitted_by_user
new_defect_create_result = #rally.create(:defect, new_defect)
puts "New Defect created FormattedID: #{new_defect_create_result.FormattedID}"

Resources