Class: RallyAPI::RallyRestJson

Inherits:
Object
  • Object
show all
Defined in:
lib/rally_api/rally_rest_json.rb

Overview

Main Class to instantiate when using the tool

Constant Summary collapse

DEFAULT_WSAPI_VERSION =
"1.43"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ RallyRestJson

Returns a new instance of RallyRestJson.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rally_api/rally_rest_json.rb', line 54

def initialize(args)
  pre_init()

  auth_info = {}

  auth_info[:base_url]  = @rally_url = args[:base_url] || "https://rally1.rallydev.com/slm"
  auth_info[:username]  = args[:username]
  auth_info[:password]  = args[:password]
  auth_info[:api_key]   = args[:api_key]
  @rally_workspace_name = args[:workspace]
  @rally_project_name   = args[:project]
  @wsapi_version        = args[:version]  || DEFAULT_WSAPI_VERSION
  @rally_headers        = args[:headers]  || CustomHttpHeader.new
  @proxy_info           = args[:proxy]
  @skip_sec_key         = args[:skip_sec_key]

  #flag to help RallyRestAPI users to use snake case field names eg Defect.fixed_in_build vs Defect["FixedInBuild"]
  @rally_rest_api_compat  = args[:rally_rest_api_compat] || false

  @low_debug = args[:debug]  || false
  @logger    = args[:logger] || nil    #assumes this is an instance of Logger

  @rally_connection = RallyJsonConnection.new(@rally_headers, @low_debug, @proxy_info)
  #@rally_connection.set_client_user(@rally_url, @rally_user, @rally_password)
  @rally_connection.set_auth(auth_info)
  @rally_connection.logger  = @logger unless @logger.nil?

  if @wsapi_version.to_s.include?("v2.") && !@skip_sec_key && auth_info[:api_key].nil?
    @rally_connection.setup_security_token(security_url)
  end

  if !@rally_workspace_name.nil?
    @rally_default_workspace = find_workspace(@rally_workspace_name)
    raise StandardError, "unable to find default workspace #{@rally_workspace_name}" if @rally_default_workspace.nil?
  end

  if !@rally_project_name.nil?
    @rally_default_project = find_project(@rally_default_workspace, @rally_project_name)
    raise StandardError, "unable to find default project #{@rally_project_name}" if @rally_default_project.nil?
  end

  self
end

Instance Attribute Details

#custom_fields_for_typeObject (readonly)

Returns the value of attribute custom_fields_for_type.



52
53
54
# File 'lib/rally_api/rally_rest_json.rb', line 52

def custom_fields_for_type
  @custom_fields_for_type
end

#loggerObject

Returns the value of attribute logger.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def logger
  @logger
end

#low_debugObject

Returns the value of attribute low_debug.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def low_debug
  @low_debug
end

#proxy_infoObject

Returns the value of attribute proxy_info.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def proxy_info
  @proxy_info
end

#rally_alias_typesObject

Returns the value of attribute rally_alias_types.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_alias_types
  @rally_alias_types
end

#rally_connectionObject (readonly)

Returns the value of attribute rally_connection.



52
53
54
# File 'lib/rally_api/rally_rest_json.rb', line 52

def rally_connection
  @rally_connection
end

#rally_default_projectObject

Returns the value of attribute rally_default_project.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_default_project
  @rally_default_project
end

#rally_default_workspaceObject

Returns the value of attribute rally_default_workspace.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_default_workspace
  @rally_default_workspace
end

#rally_headersObject

Returns the value of attribute rally_headers.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_headers
  @rally_headers
end

#rally_project_nameObject

Returns the value of attribute rally_project_name.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_project_name
  @rally_project_name
end

#rally_rest_api_compatObject

Returns the value of attribute rally_rest_api_compat.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_rest_api_compat
  @rally_rest_api_compat
end

#rally_urlObject

Returns the value of attribute rally_url.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_url
  @rally_url
end

#rally_workspace_nameObject

Returns the value of attribute rally_workspace_name.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def rally_workspace_name
  @rally_workspace_name
end

#wsapi_versionObject

Returns the value of attribute wsapi_version.



49
50
51
# File 'lib/rally_api/rally_rest_json.rb', line 49

def wsapi_version
  @wsapi_version
end

Class Method Details

.camel_case_word(sym) ⇒ Object



474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/rally_api/rally_rest_json.rb', line 474

def self.camel_case_word(sym)
  word = sym.to_s

  if word.start_with?("c_")
    custom_field_without_c = word.sub("c_", "")
    camelized = camelize(custom_field_without_c)
    camelized[0] = custom_field_without_c[0]
    "c_#{camelized}"
  else
    camelize(word)
  end
end

.camelize(str) ⇒ Object

implemented basic version here to not have to include ActiveSupport



488
489
490
# File 'lib/rally_api/rally_rest_json.rb', line 488

def self.camelize(str)
  str.split('_').map {|w| w.capitalize}.join
end

.fix_case(values) ⇒ Object



467
468
469
470
471
472
# File 'lib/rally_api/rally_rest_json.rb', line 467

def self.fix_case(values)
  values.inject({}) do |new_values, (key, value)|
    new_values[camel_case_word(key)] = value.is_a?(Hash) ? fix_case(value) : value
    new_values
  end
end

Instance Method Details

#adjust_find_threads(num_threads) ⇒ Object



261
262
263
# File 'lib/rally_api/rally_rest_json.rb', line 261

def adjust_find_threads(num_threads)
  @rally_connection.set_find_threads(num_threads)
end

#allowed_values(type, field, workspace = @rally_default_workspace) ⇒ Object

todo - check support for portfolio item fields



326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/rally_api/rally_rest_json.rb', line 326

def allowed_values(type, field, workspace = @rally_default_workspace)
  type_def = get_typedef_for(type, workspace)
  allowed_vals = {}
  type_def["Attributes"].each do |attr|
    next if attr["ElementName"] != field
    attr["AllowedValues"].each do |val_ref|
      val = val_ref["StringValue"]
      val = "Null" if val.nil? || val.empty?
      allowed_vals[val] = true
    end
  end
  allowed_vals
end

#create(type, fields, params = {}) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/rally_api/rally_rest_json.rb', line 145

def create(type, fields, params = {})
  type = check_type(type)
  if (fields["Workspace"].nil? && fields["Project"].nil?)
    fields["Workspace"] = @rally_default_workspace._ref unless @rally_default_workspace.nil?
    fields["Project"] = @rally_default_project._ref unless @rally_default_project.nil?
  end

  ws_ref = fields["Workspace"]
  ws_ref = ws_ref["_ref"] unless ws_ref.class == String || ws_ref.nil?
  params[:workspace] = ws_ref

  fields = RallyAPI::RallyRestJson.fix_case(fields) if @rally_rest_api_compat
  object2create = { type => check_fields(fields) }
  args = { :method => :post, :payload => object2create }
  #json_response = @rally_connection.create_object(make_create_url(rally_type), args, object2create)
  json_response = @rally_connection.send_request(make_create_url(type), args, params)
  #todo - check for warnings
  RallyObject.new(self, json_response["CreateResult"]["Object"], warnings(json_response)).read()
end

#custom_fields_for(type, workspace = @rally_default_workspace) ⇒ Object



340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/rally_api/rally_rest_json.rb', line 340

def custom_fields_for(type, workspace = @rally_default_workspace)
  @custom_fields_for_type[workspace.ObjectID] = {} if @custom_fields_for_type[workspace.ObjectID].nil?
  if @custom_fields_for_type[workspace.ObjectID][type].nil?
    @custom_fields_for_type[workspace.ObjectID][type] = {}
    type_def = get_typedef_for(type, workspace)
    type_def["Attributes"].each do |attr|
      next if attr["Custom"].to_s == "false"
      elem_name = attr["ElementName"]
      elem_name = elem_name.slice(2..256) unless @wsapi_version.start_with?("1")
      @custom_fields_for_type[workspace.ObjectID][type][elem_name] = attr["ElementName"]
    end
  end
  return @custom_fields_for_type[workspace.ObjectID][type]
end

#debug_logging_offObject



103
104
105
106
# File 'lib/rally_api/rally_rest_json.rb', line 103

def debug_logging_off
  @low_debug = false
  @rally_connection.low_debug = false
end

#debug_logging_onObject



98
99
100
101
# File 'lib/rally_api/rally_rest_json.rb', line 98

def debug_logging_on
  @low_debug = true
  @rally_connection.low_debug = true
end

#delete(ref_to_delete) ⇒ Object



176
177
178
179
180
181
# File 'lib/rally_api/rally_rest_json.rb', line 176

def delete(ref_to_delete)
  args = { :method => :delete }
  #json_response = @rally_connection.delete_object(ref_to_delete, args)
  json_response = @rally_connection.send_request(ref_to_delete, args)
  json_response["OperationResult"]
end

#find(query_obj = RallyQuery.new) {|query_obj| ... } ⇒ Object


Querying Rally example test_query = RallyAPI::RallyQuery.new() test_query.type = :defect test_query.fetch = “Name” test_query.workspace = {“_ref” => “rally1.rallydev.com/slm/webservice/1.25/workspace/12345.js” } #optional test_query.project = {“_ref” => “rally1.rallydev.com/slm/webservice/1.25/project/12345.js” } #optional test_query.page_size = 200 #optional - default is 200 test_query.limit = 1000 #optional - default is 99999 test_query.project_scope_up = false test_query.project_scope_down = true test_query.order = “Name Asc” test_query.query_string = “(Severity = "High")”

results = @rally.find(test_query)

tip - set the fetch string of the query to the fields you need - only resort to the read method if you want your code to be slow results.each do |defect|

puts defect.Name   # or defect["Name"]
defect.read    #read the whole defect from Rally to get all fields (eg Severity)
puts defect.Severity

end query_obj is RallyQuery

Yields:

  • (query_obj)


242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/rally_api/rally_rest_json.rb', line 242

def find(query_obj = RallyQuery.new)
  yield query_obj if block_given?

  if query_obj.workspace.nil?
    query_obj.workspace = @rally_default_workspace unless @rally_default_workspace.nil?
  end

  errs = query_obj.validate()
  if errs.length > 0
    raise StandardError, "Errors making Rally Query: #{errs.to_s}"
  end

  query_url = make_query_url(@rally_url, @wsapi_version, check_type(query_obj.type.to_s))
  query_params = query_obj.make_query_params
  args =  {:method => :get}
  json_response = @rally_connection.get_all_json_results(query_url, args, query_params, query_obj.limit)
  RallyQueryResult.new(self, json_response, warnings(json_response))
end

#find_project(workspace_object, project_name) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/rally_api/rally_rest_json.rb', line 121

def find_project(workspace_object, project_name)
  if workspace_object.nil?
    raise StandardError, "A workspace must be provided to find a project"
  end

  query = RallyQuery.new()
  query.type          = :project
  query.query_string  = "((Name = \"#{project_name}\") AND (State = \"Open\"))"
  query.limit         = 20
  query.fetch         = true
  query.workspace     = workspace_object

  results = find(query)
  return results.first if results.length > 0
  nil
end

#find_workspace(workspace_name) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/rally_api/rally_rest_json.rb', line 108

def find_workspace(workspace_name)
  sub = self.user["Subscription"].read({:fetch => "Workspaces,Name,State"})
  workspace = nil
  sub.Workspaces.each do |ws|
    #ws.read
    if (ws["Name"] == workspace_name) && (ws["State"] == "Open")
      workspace = ws
      break  #doing a break for performance some customers have 100+ workspaces - no need to do the others
    end
  end
  workspace
end

#get_fields_for(type, workspace = @rally_default_workspace) ⇒ Object



314
315
316
317
318
319
320
321
322
323
# File 'lib/rally_api/rally_rest_json.rb', line 314

def get_fields_for(type, workspace = @rally_default_workspace)
  type_def = get_typedef_for(type, workspace)
  return nil if type_def.nil?
  fields = {}
  type_def["Attributes"].each do |attr|
    field_name = attr["ElementName"]
    fields[field_name] = attr
  end
  fields
end

#get_typedef_for(type, workspace = @rally_default_workspace) ⇒ Object



302
303
304
305
306
307
308
309
310
311
312
# File 'lib/rally_api/rally_rest_json.rb', line 302

def get_typedef_for(type, workspace = @rally_default_workspace)
  type = type.to_s if type.class == Symbol
  type = check_type(type)
  type_def_query             = RallyQuery.new()
  type_def_query.type        = "typedefinition"
  type_def_query.workspace   = workspace
  type_def_query.fetch       = true
  type_def_query.query_string= "(TypePath = \"#{type}\")"
  type_def = find(type_def_query)
  type_def.first
end

#rank_above(ref_to_rank, relative_ref) ⇒ Object

rankAbove=%2Fhierarchicalrequirement%2F4624552599 href="https://rally1.rallydev.com/slm/webservice/1.27/hierarchicalrequirement/4616818613.js">rally1.rallydev.com/slm/webservice/1.27/hierarchicalrequirement/4616818613.js”}



267
268
269
270
271
272
273
274
275
276
277
# File 'lib/rally_api/rally_rest_json.rb', line 267

def rank_above(ref_to_rank, relative_ref)
  ref = ref_to_rank
  params = {}
  params[:rankAbove] = short_ref(relative_ref)
  params[:fetch] = "true"
  json_update = { get_type_from_ref(ref_to_rank) => {"_ref" => ref_to_rank} }
  args = { :method => :put, :payload => json_update }
  #update = @rally_connection.put_object(ref, args, params, json_update)
  json_response = @rally_connection.send_request(ref, args, params)
  RallyObject.new(self, json_response["OperationResult"]["Object"], warnings(json_response))
end

#rank_below(ref_to_rank, relative_ref) ⇒ Object

ref to object.js? rankBelow=%2Fhierarchicalrequirement%2F4624552599



280
281
282
283
284
285
286
287
288
289
# File 'lib/rally_api/rally_rest_json.rb', line 280

def rank_below(ref_to_rank, relative_ref)
  ref = ref_to_rank
  params = {}
  params[:rankBelow] = short_ref(relative_ref)
  params[:fetch] = "true"
  json_update = { get_type_from_ref(ref_to_rank) => {"_ref" => ref_to_rank} }
  args = { :method => :put, :payload => json_update }
  json_response = @rally_connection.send_request(ref, args, params)
  RallyObject.new(self, json_response["OperationResult"]["Object"], warnings(json_response))
end

#rank_to(ref_to_rank, location = "TOP") ⇒ Object



291
292
293
294
295
296
297
298
299
300
# File 'lib/rally_api/rally_rest_json.rb', line 291

def rank_to(ref_to_rank, location = "TOP")
  ref = ref_to_rank
  params = {}
  params[:rankTo] = location
  params[:fetch]  = "true"
  json_update = { get_type_from_ref(ref_to_rank) => {"_ref" => ref_to_rank} }
  args = { :method => :put, :payload => json_update }
  json_response = @rally_connection.send_request(ref, args, params)
  RallyObject.new(self, json_response["OperationResult"]["Object"], warnings(json_response))
end

#read(type, obj_id, params = {}) ⇒ Object



166
167
168
169
170
171
172
173
174
# File 'lib/rally_api/rally_rest_json.rb', line 166

def read(type, obj_id, params = {})
  type = check_type(type)
  ref = check_id(type.to_s, obj_id)
  params[:workspace] = @rally_default_workspace.ref if params[:workspace].nil?
  args = { :method => :get }
  json_response = @rally_connection.send_request(ref, args, params)
  rally_type = json_response.keys[0]
  RallyObject.new(self, json_response[rally_type], warnings(json_response))
end

#read_collection(collection_hash, params = {}) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
# File 'lib/rally_api/rally_rest_json.rb', line 194

def read_collection(collection_hash, params = {})
  collection_count = collection_hash['Count']
  start = 1
  pagesize = params[:pagesize] || 200
  full_collection = []
  start.step(collection_count, pagesize).each do |page_start|
    page = reread(collection_hash, {:pagesize => 200, :startindex => page_start})
    full_collection.concat(page["Results"])
  end
  {"Results" => full_collection}
end

#reread(json_object, params = {}) ⇒ Object



183
184
185
186
187
188
189
190
191
192
# File 'lib/rally_api/rally_rest_json.rb', line 183

def reread(json_object, params = {})
  args = { :method => :get }
  if params[:workspace].nil? && (json_object["Workspace"] && json_object["Workspace"]["_ref"])
    params[:workspace] = json_object['Workspace']['_ref']
  end
  #json_response = @rally_connection.read_object(json_object["_ref"], args, params)
  json_response = @rally_connection.send_request(json_object["_ref"], args, params)
  rally_type = json_response.keys[0]
  json_response[rally_type]
end

#update(type, obj_id, fields, params = {}) ⇒ Object Also known as: update_ref



206
207
208
209
210
211
212
213
214
215
# File 'lib/rally_api/rally_rest_json.rb', line 206

def update(type, obj_id, fields, params = {})
  type = check_type(type)
  ref = check_id(type.to_s, obj_id)
  fields = RallyAPI::RallyRestJson.fix_case(fields) if @rally_rest_api_compat
  json_update = {type.to_s => check_fields(fields)}
  args = {:method => :post, :payload => json_update}
  json_response = @rally_connection.send_request(ref, args, params)
  #todo check for warnings on json_response["OperationResult"]
  RallyObject.new(self, reread({"_ref" => ref}), warnings(json_response))
end

#user(params = {}) ⇒ Object



138
139
140
141
142
143
# File 'lib/rally_api/rally_rest_json.rb', line 138

def user(params = {})
  args = { :method => :get }
  json_response = @rally_connection.send_request(make_get_url("user"), args, params)
  rally_type = json_response.keys[0]
  RallyObject.new(self, json_response[rally_type], warnings(json_response))
end