Class: BrocadeREST::RestController

Inherits:
Object
  • Object
show all
Defined in:
lib/brocade/restcontroller.rb

Direct Known Subclasses

VTMController

Instance Method Summary collapse

Constructor Details

#initialize(user, pass, uri, restVersion, manifestClass, loggerLevel = 0, root = nil, expandArrays = true) ⇒ RestController

Returns a new instance of RestController.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/brocade/restcontroller.rb', line 19

def initialize(user, pass, uri, restVersion, manifestClass, loggerLevel=0, root=nil, expandArrays=true)
	@loggerLevel = Integer(loggerLevel)
	@restVersion = restVersion
	@uri = URI.parse( uri.end_with?('/')? uri : uri<<'/' )
	@user = user
	@pass = pass
	@expandArrays = expandArrays
	@http = Net::HTTP.new(@uri.host, @uri.port)
	@http.use_ssl = true
	@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
	@probeName = "RestfulRubyProbe"
	@root = root
	@walkType = WalkTypes::READ
	@manifestClass = manifestClass
	@manifests = {}
	@objects = {}
	@knownParams = {}
	@preReq = {} 
	@rewalk = {}
	@qm = nil
	@workdir = nil
	@generateOutOfTreeManifests = false
	@errors = [];
end

Instance Method Details

#continueOnError(cont) ⇒ Object

Contiue on Error? Attempt to continue if we encounter problems Currentlu just allows outoftree manifests to be attempted.



71
72
73
# File 'lib/brocade/restcontroller.rb', line 71

def continueOnError(cont)
	@generateOutOfTreeManifests = cont
end

#deepCompare(name, hash1, hash2, failFast, errors = 0) ⇒ Object

Recurse over the hash and compare all elements. Simply using hash == hash can fail when the keys are in a different order.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/brocade/restcontroller.rb', line 201

def deepCompare(name, hash1, hash2, failFast, errors=0)
	if hash1.is_a?(Hash)
		if hash2.nil?
			logger(1,"DeepCompare: #{name}, No Match '#{hash1}' vs 'nil'")
			@errors.push("DeepCompare: #{name}, No Match '#{hash1}' vs 'nil'")
			failFast ? (return false) : (return errors+1)
		end
		hash1.each do |key,value|
			if ( hash2.include?(key) )
				result = deepCompare("#{name}:#{key}", value, hash2[key], failFast, errors)
				( failFast and (!result) ) ? (return false) : errors = result
			else
				logger(1,"DeepCompare: #{name}, Missing Key '#{key}'")
				@errors.push("DeepCompare: #{name}, Missing Key '#{key}'")
				failFast ? (return false) : (return errors+1)
			end
		end
		failFast ? (return true) : (return errors)
	elsif hash1.is_a?(Array)
		# Check array lengths match
		if hash1.length != hash2.length
			logger(1, "DeepCompare: #{name}, Size differs: #{hash1.length} vs #{hash2.length}")
			@errors.push("DeepCompare: #{name}, Size differs: #{hash1.length} vs #{hash2.length}")
			failFast ? (return false) : (return errors+1)
		end
		# sort arrays before comparing
		sort1 = hash1.sort_by { |h| h.to_s }
		sort2 = hash2.sort_by { |h| h.to_s }
		sort1.each do |item1|
			item2 = sort2.shift
			result = deepCompare("#{name}:#{item1}", item1, item2, failFast, errors)
			( failFast and (!result) ) ? ( return false ) : errors = result
		end	
		failFast ? ( return true ) : ( return errors )
	else
		if ( hash1 != hash2 )
			logger(1,"DeepCompare: #{name}, No Match '#{hash1}' vs '#{hash2}'")
			@errors.push("DeepCompare: #{name}, No Match: #{hash1} vs #{hash2}")
			failFast ? (return false) : (return errors+1)
		end
	end
	failFast ? (return true) : (return errors)
end

#deleteObject(object) ⇒ Object

DELETE the provided http string



153
154
155
156
157
158
# File 'lib/brocade/restcontroller.rb', line 153

def deleteObject(object)
	uri = parseURI(object)
	response = do_delete(uri)
	return nil if response == nil
	return response
end

#do_delete(uri) ⇒ Object

do the delete



129
130
131
132
133
134
# File 'lib/brocade/restcontroller.rb', line 129

def do_delete(uri)
	request = Net::HTTP::Delete.new(uri.request_uri)
	request.basic_auth @user, @pass
	response = @http.request(request)
	return response
end

#do_get(uri) ⇒ Object

do the get



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/brocade/restcontroller.rb', line 102

def do_get(uri)
	request = Net::HTTP::Get.new(uri.request_uri)
	request.basic_auth @user, @pass
	response = @http.request(request)
	case response
		when Net::HTTPSuccess then
			return response
		else
			logger(1, "HTTP Call Failed: #{uri}, Response: #{response}")
			return response
	end
end

#do_put(uri, body, ct = "application/json") ⇒ Object

do the put



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/brocade/restcontroller.rb', line 116

def do_put(uri, body, ct="application/json")
	logger(1, "REST PUT: #{uri}")
	logger(2, "REST ContentType: #{ct}")
	logger(3, "REST Body: #{body}")
	request = Net::HTTP::Put.new(uri.request_uri)
	request.basic_auth @user, @pass
	request['Content-Type'] = ct
	request.body=body
	response = @http.request(request)
	return response
end

#dumpConfig(type = :manifests, manOut = nil, tmpOut = nil, binOut = nil, instvar = true) ⇒ Object

Dump out the Manifests to the console, and write to outputDir if provided



417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/brocade/restcontroller.rb', line 417

def dumpConfig(type=:manifests, manOut=nil, tmpOut=nil, binOut=nil, instvar=true)
	if (type == :manifests) or ( type == :all )
		@manifests.each do |name,manifest|
			manifest.dump()
			if tmpOut != nil
				manifest.genTemplate(tmpOut,instvar)
			end
			if manOut != nil
				manifest.genManifest(manOut)
			end
			if binOut != nil
				manifest.genBinary(binOut)
			end
		end
	end
	if ( type == :objects ) or ( type == :all )
		@objects.each do |name,manifest|
			manifest.dump()
			if name.start_with?("traffic_managers_")
				next;
			end
			if tmpOut != nil
				manifest.genTemplate(tmpOut,instvar)
			end
			if manOut != nil
				manifest.genManifest(manOut, true)
			end
			if binOut != nil
				manifest.genBinary(binOut)
			end
		end
	end
end

#dumpNodeConfig(outfile, allParams = true, builtin = true, manifestDir = "#{@workdir}/manifests/", binDir = nil) ⇒ Object

Write a node config to the given outfile. By default we write all configuration to the outfile, however… If allParams is false, then ignore params which are using defaults If builtin is false, then don’t create config for built-in objects



396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# File 'lib/brocade/restcontroller.rb', line 396

def dumpNodeConfig(outfile, allParams=true, builtin=true, manifestDir="#{@workdir}/manifests/", binDir=nil)

	@objects.each do |name,manifest|
		if (!manifest.isBinary)
			type_ = manifest.getType
			parent = manifest.findParent("#{manifestDir}/#{type_}",".pp")
			if ( (!parent.nil?) and (!@qm.nil?) )
				qh = @qm.getQuirk(parent.chomp(".pp"));
				if ( qh != nil and qh.is_a?(Hash) and qh.has_key?(:readFunc) )
					json = @qm.send(qh[:readFunc], manifest.getJSON )
					manifest.setJSON(json)
				end
			end
		end
		preReq = Marshal.load(Marshal.dump(@preReq))
		manifest.genNodeConfig(outfile, allParams, builtin, preReq, manifestDir, binDir)
	end

end

#findNeededParams(name, uri, parent, jsonError) ⇒ Object

This is called by the probe when it encounters missing mandatory parameters. Ask the user what to do, providing a suggested answer if one exists in the knownparams data. Also update the puppetmanifest object to inform it about the required parameter.



589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
# File 'lib/brocade/restcontroller.rb', line 589

def findNeededParams(name, uri, parent, jsonError)
	if (jsonError.class == Hash && jsonError.has_key?("error_id"))
		logger(5, jsonError.inspect)
		case jsonError["error_id"]
			when "resource.validation_error" then
				logger(4, "Resource Validation Error: Top Level")
				return findNeededParams(name, uri, parent, jsonError["error_info"] )
			when "property.no_default" then
				logger(4, "Resource Validation Error: No Default for #{parent}")
				print("Mandatory Parameter Required - Please enter a value for: #{name} -> #{parent}: ")
				if @knownParams[name] != nil and @knownParams[name].has_key?(parent)
					example = @knownParams[name][parent][1]
					example = @probeName if example == "_TESTOBJECT_"
					example = Integer(example) if @knownParams[name][parent][0] == "integer"
				else
					example = @probeName
				end
				print "[Default: #{example}]: "
				new = $stdin.gets.chomp()
				if ( new != "" )
					example = new
					example = Integer(example) if example.match(/^\d+$/) 
				end
				logger(4, "Adding Required Param: #{parent} to manifest: #{name}")
				@manifests[name].addRequiredParam(parent, example)
				return example
			when "filename.forbiddenpath" then
				logger(4, "Can't use that name. Barf")
			when "json.wrong_type" then
				logger(4,"REST reports wrong type")
			else
				logger(4, "Unhandled JSON Error #{jsonError}")
		end
	else
		newFields = {}
		if ( jsonError.class == Array )
			jsonError.each do |child|
				if parent != nil
					param = parent+":"+child
				else
					param = child
				end
				newFields[child] = findNeededParams(name, uri, param, jsonError[child])
			end
		elsif ( jsonError.class == Hash )
			jsonError.each do |child,json|
				if parent != nil
					param = parent+"__"+child
				else
					param = child
				end
				newFields[child] = findNeededParams(name, uri, param, json)
			end
		else
			return jsonError
		end
		return newFields
	end
end

#getErrorsObject

Return errors not yet reported.



58
59
60
61
62
# File 'lib/brocade/restcontroller.rb', line 58

def getErrors() 
	$errors = @errors
	#@errors = []
	return $errors;
end

#getObject(object) ⇒ Object

GET the provided http string



137
138
139
140
141
142
# File 'lib/brocade/restcontroller.rb', line 137

def getObject(object)
	uri = parseURI(object)
	response = do_get(uri)
	return nil if response == nil
	return response
end

#loadKnownParams(filename) ⇒ Object

Load known parameters to use as default answers to mandatory params. Used when we walk the API.



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/brocade/restcontroller.rb', line 316

def loadKnownParams(filename)
	@knownParams = {}
	if (!File.exist? filename )
		logger(-1, "Error, Known Params File does not exist: #{filename}")
		return
	end
	logger(1, "Parsing Known Params File: #{filename}")
	kpf = File.open( filename )
	kpf.each_line do |line|
		entry = line.chomp.split(',')
		object = entry.shift
		if @knownParams.has_key?(object)
			@knownParams[object][entry.shift] = entry
		else
			@knownParams[object] =  { entry.shift => entry } 
		end
	end		
	kpf.close
end

#loadPreRequisites(filename) ⇒ Object

read in the preRequisites file. This is used by genNodeConfig when generating the required paramater on resources.



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/brocade/restcontroller.rb', line 338

def loadPreRequisites(filename)
	@preReq = {}
	if (!File.exist? filename)
		logger(-1, "Error, PreRequisites File does not exist: #{filename}")
		return
	end
	logger(1, "Parsing PreRequisites File: #{filename}")
	prf = File.open( filename )
	prf.each_line do |line|
		entry = line.chomp.split(',')
		type = entry.shift
		if @preReq.include?(type)
			@preReq[type].push entry
		else
			@preReq[type] = [ entry ] 
		end
	end
	prf.close
end

#loadWalkOrderingObject



358
359
360
361
362
# File 'lib/brocade/restcontroller.rb', line 358

def loadWalkOrdering()
	walkOrder = [ "monitors", "rules", "ssl_", "aptimizer", "locations", 
						"dns_", "glb_services", "kerberos_keytabs", "kerberos", 
						"pools", "traffic_ip_groups", "virtual_servers" ]
end

#logger(level, msg) ⇒ Object

Logger function to write log messages (level<0 - Error, level==0 - Notice, level>0 - Debug )



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/brocade/restcontroller.rb', line 45

def logger(level, msg)
	if ( @loggerLevel >= level )
		if level < 0
			$stderr.puts("ERROR: BrocadeREST: #{msg}")
		elsif level == 0
			$stdout.puts("Notice: BrocadeREST: #{msg}")
		else
			$stderr.puts("Debug: BrocadeREST: #{level}: #{msg}")
		end
	end
end

#newManifest(uri, object) ⇒ Object

Generate a new manifest.



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/brocade/restcontroller.rb', line 365

def newManifest(uri, object)
	if( ! uri.path.start_with?(@uri.path) )
		logger(-1, "This object is not in the config tree? If you have switched REST versions, this could cause problems")
		if @generateOutOfTreeManifests
			logger(-1, "Trying to Continue...")
		else
			return nil
		end
	end
	type = uri.path.byteslice(@uri.path.length..uri.path.length)
	type = type.chop() if ( type.end_with?("/") )
	name = type.gsub("/","_")
	newPM = @manifestClass.new(type,uri,@restVersion,object,@root,@expandArrays)
	if ( object )
		if ( ! @objects.include?(name) )
			@objects[name] = newPM
			logger(2,"New Object: #{name}: #{uri}")
		end
	else
		if ( ! @manifests.include?(name) )
			@manifests[name] = newPM
			logger(2,"New Manifest: #{name}: #{uri}")
		end
	end
	return name
end

#objectCompare(name, content, type, internal, failFast = true) ⇒ Object

Object Compare Function



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/brocade/restcontroller.rb', line 161

def objectCompare(name, content, type, internal, failFast=true) 
	uri = parseURI(name)
	restResponse = do_get(uri)
	if ( restResponse == nil )
		@errors.push("Something Went wrong with the REST call. Nil response")
		return nil
	elsif ( restResponse.code != "200" )
		@errors.push("HTTP Call Failed: #{name}, Response: #{restResponse}")
		return false
	end
	if type == "application/json"
		if (!@qm.nil?)
			qh = @qm.getQuirk(internal);
			if ( qh != nil and qh.is_a?(Hash) and qh.has_key?(:compareFunc) )
				input = @qm.send(qh[:compareFunc], uri, content)
			else
				input = JSON.parse(content)
			end
		else
			input = JSON.parse(content)
		end
		rest = JSON.parse(restResponse.body)
		if failFast
			return deepCompare(name,input,rest,failFast)
		else
			( deepCompare(name,input,rest,failFast) > 0 ) ? (return false) : (return true)
		end
	else
		rest = restResponse.body
		input = content.force_encoding(rest.encoding)
		if ( rest == input ) 
			return true
		end
	end
	@errors.push("Binary object exists, but does not match.")
	return false
end

#objectCreate(name, content, type, internal) ⇒ Object

Object Create function



246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/brocade/restcontroller.rb', line 246

def objectCreate(name, content, type, internal)
	uri = parseURI(name)
	if type == "application/json"
		if(!@qm.nil?)
			qh = @qm.getQuirk(internal);
			if ( qh != nil and qh.is_a?(Hash) and qh.has_key?(:writeFunc) )
				content = @qm.send(qh[:writeFunc], uri, content)
			end
		end
	end
	return do_put(uri, content, type)
end

#objectDelete(name) ⇒ Object

Object Delete function



260
261
262
# File 'lib/brocade/restcontroller.rb', line 260

def objectDelete(name)
	return deleteObject(name)
end

#objectPurge(stateDir) ⇒ Object

purge the REST API of unknown configuration objects. stateDir should contain a file for each object type with a line for each object Any children we find in an object tree, which do not appear in the file will be deleted.



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/brocade/restcontroller.rb', line 268

def objectPurge(stateDir)
	Dir.glob("#{stateDir}/*").each do |type|
		logger(1, "Purge: Checking state file: #{type}")
		uri = @uri.clone()
		# Read the state file and then delete it
		items = IO.readlines(type)
		File.unlink(type)
		# dont purge anything in root of configuration tree
		if (items.empty? or (!items[0].include?('/')))
			next
		end
		parent = items[0][0..items[0].rindex('/')]
		uri.path += parent
		logger(1, "Purge: Checking URI: #{uri}")
		response = do_get(uri)
		if response == nil
			logger(-1, "Purge: Failed to read URI: #{uri.path}. Response is nil")
			next
		elsif response.code != "200"
			logger(-1, "Purge: Failed to read URI: #{uri.path}. Response code: #{response.code}")
			next
		elsif ( response.content_type() != "application/json" )
			logger(-1, "Purge: Failed to read URI: #{uri.path}, Response was not JSON.")
			next
		else
			json = JSON.parse(response.body)
			if ( json == nil )
				logger(-1, "Purge: Failed to parse JSON: #{uri.path}.")
				next
			elsif (! json.has_key?("children") )
				logger(-1, "Purge: Failed to parse JSON: #{uri.path}, Response has no Children.")
				next
			end
			items.each {|item| item.strip!().gsub!('%20', ' ')}
			json["children"].each do |child|
				logger(2, "Purge: Child: #{child}" )
				if (! items.include?("#{parent}#{child["name"]}") )
					logger(0,"Purge: Removing unknown object: #{parent}#{child["name"]}")
					deleteObject(child["href"])
				end
			end
		end
	end
	return true
end

#parseURI(uri) ⇒ Object

Return a new uri object for the provided path, by cloning our core @uri and updating the path elements. Return nil if we jump hosts.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/brocade/restcontroller.rb', line 77

def parseURI(uri)
	newURI = @uri.clone()
	if ( uri.start_with?("/") )
		newURI.path = uri
		return newURI
	elsif ( uri.start_with?("http") )
		fqURI = URI.parse(uri)
		if ( fqURI.host != @uri.host ) || ( fqURI.port != @uri.port ) 
			then logger(-1, "Warning... Host or Port changed!")
			if @generateOutOfTreeManifests
				return fqURI
			else
				return nil
			end
		else
			return fqURI
		end	
	else
		newURI.path += "/" if ( ! newURI.path.end_with?("/") )
		newURI.path += uri
		return newURI
	end
end

#probe(uri, json, attempt = 0) ⇒ Object

function to probe the API by attempting to create a new object within the tree named @probeName We detect whether the API is expecting JSON or binary data, as well as any mandatory parameters



535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'lib/brocade/restcontroller.rb', line 535

def probe(uri, json, attempt=0)
	attempt = attempt + 1
	if (attempt > 5)
		abort("FAILED to Probe: #{uri}")
	end
	result = { }  
	testObject = uri.clone()
	testObject.path.end_with?("/")? testObject.path += @probeName : testObject.path += "/#{@probeName}"
	logger(1,"Probe: #{testObject.path} - Attempt: #{attempt}")
	body = JSON.generate(json)
	response = do_put(testObject,body)
	case response
		when Net::HTTPSuccess then
			logger(4, "Probe: Body: #{response.body}" )
			logger(4, "Probe: Complete.")
			return response.body
		when Net::HTTPUnsupportedMediaType then
			logger(4, "Probe: Binary Upload Expected" )
			response = do_put(testObject, "foo\tbar\n", "application/octet-stream")
			logger(4, response)
			logger(4, "Probe: Complete.")
			return :BINARY
		when Net::HTTPForbidden then
			logger(4, "Probe: Invalid Resource")
			logger(4, "Probe: Complete.")
			return nil
		when Net::HTTPBadRequest then
			logger(4, "Probe: Mandatory parameter needed")
			name = newManifest(uri,false)
			if name.nil?
				logger(-1, "(BUG?) newManifest returned nil for: #{uri}")
				return nil
			end
			jsonError = JSON.parse(response.body)
			newJSON = (findNeededParams(name, uri, nil, jsonError))
			if ( newJSON == nil )
				logger(1, "Probe Failed: #{uri}")
				return nil
			end
			if @root.nil?
				json = newJSON 
			else
				json[@root] = newJSON
			end
			return probe(uri, json, attempt)
		else
			logger(4, "Probe: Unhandled: #{response}" )
			return nil
	end
end

#putObject(object, body, contentType) ⇒ Object

PUT the provided http string



145
146
147
148
149
150
# File 'lib/brocade/restcontroller.rb', line 145

def putObject(object, body, contentType)
	uri = parseURI(object)
	response = do_put(uri, body, contentType)
	return nil if response == nil
	return response
end

#setType(walkType) ⇒ Object

set Walktype to :READ, :PROBE, or :DELETE



65
66
67
# File 'lib/brocade/restcontroller.rb', line 65

def setType(walkType)
		@walkType = walkType
end

#walk(uri = @uri.clone) ⇒ Object

Recursive function to walk the REST API.



452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
# File 'lib/brocade/restcontroller.rb', line 452

def walk(uri=@uri.clone)
	logger(1, "Walking: #{uri}" )
	jsonStub = {}
	if @root
		jsonStub[@root] = {}
	end 
	response = do_get(uri)
	if ( response == nil )
		logger(-1, "WALK Failed")
		return
	end
	if ( response.content_type() == "application/json" ) 
		json = JSON.parse(response.body)
		if (json.is_a?(Hash) and json.has_key?("children"))
			logger(2, "Children: #{json}" )
			if ( json["children"].empty? )
				logger(2,"Empty Tree: #{uri}")
			end
			logger(2,"Probing: #{uri}")
			probe = probe(uri, jsonStub) if @walkType == WalkTypes::PROBE
			if ( probe != nil )
				logger(2, "Creating Manifest for: #{uri}")
				name = newManifest(uri,false)
				if name.nil?
					logger(-1, "ERROR - (BUG?) newManifest returned nil for: #{uri}")
				elsif ( probe == :BINARY )
					@manifests[name].setBinary(true)
				else
					qh = @qm.getQuirk(name);
				if ( qh != nil and qh.is_a?(Hash) and qh.has_key?(:manifest) )
						quirkyJSON = qh[:manifest]
						@manifests[name].setJSON(quirkyJSON)
						if qh.has_key?(:required)
							qh[:required].each do |quirkyReqs|
								@manifests[name].addRequiredParam(quirkyReqs["name"],quirkyReqs["example"])
							end
						end
					else
						@manifests[name].setJSON(probe)
					end
				end
			end
			json["children"].each do |child|
				logger(2, child )
				nextURI = parseURI( child["href"] )
				walk( nextURI )
			end
		else
			logger(3, json )
			if @walkType == WalkTypes::PROBE or @walkType == WalkTypes::READ
				# Existing JSON object
				name = newManifest(uri,true)
				if name.nil?
					logger(-1, "(BUG?) newManifest returned nil for: #{uri}")
				else
					@objects[name].setJSON(response.body)
				end
			elsif @walkType == WalkTypes::DELETE && uri.path.end_with?(@probeName)
				logger(3, "Deleting Object: #{uri}")
				logger(3, do_delete(uri).body)
			end
		end
	else
		if @walkType == WalkTypes::PROBE or @walkType == WalkTypes::READ
			# Existing binary object
			name = newManifest(uri,true)
			if name.nil?
				logger(-1, "(BUG?) newManifest returned nil for: #{uri}")
			else
				@objects[name].setBinary(true)
				@objects[name].setData(response.body)
				logger(3, response.body )
			end
		elsif @walkType == WalkTypes::DELETE && uri.path.end_with?(@probeName)
			logger(3, "Deleting Object: #{uri}")
			logger(3, do_delete(uri).body)
		end
	end
	return true
end