kinetic_sdk 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +5 -5
  2. data/.yardoc-includes/yard-helpers.rb +14 -0
  3. data/.yardopts +7 -0
  4. data/CHANGELOG.md +41 -0
  5. data/GettingStarted.md +6 -12
  6. data/README.md +85 -37
  7. data/Rakefile +13 -0
  8. data/kinetic_sdk.gemspec +33 -0
  9. data/lib/kinetic_sdk/agent/agent-sdk.rb +90 -0
  10. data/lib/kinetic_sdk/agent/lib/bridges.rb +92 -0
  11. data/lib/kinetic_sdk/agent/lib/filestores.rb +91 -0
  12. data/lib/kinetic_sdk/agent/lib/handler.rb +91 -0
  13. data/lib/kinetic_sdk/bridgehub/bridgehub-sdk.rb +11 -3
  14. data/lib/kinetic_sdk/bridgehub/lib/access_keys.rb +5 -5
  15. data/lib/kinetic_sdk/bridgehub/lib/bridge.rb +5 -5
  16. data/lib/kinetic_sdk/{request_ce/request-ce-sdk.rb → core/core-sdk.rb} +30 -16
  17. data/lib/kinetic_sdk/core/lib/attribute_definitions.rb +500 -0
  18. data/lib/kinetic_sdk/core/lib/bridges.rb +141 -0
  19. data/lib/kinetic_sdk/{request_ce → core}/lib/categories.rb +3 -3
  20. data/lib/kinetic_sdk/{request_ce → core}/lib/datastore_form.rb +8 -8
  21. data/lib/kinetic_sdk/{request_ce → core}/lib/datastore_submissions.rb +20 -9
  22. data/lib/kinetic_sdk/{request_ce → core}/lib/form.rb +7 -7
  23. data/lib/kinetic_sdk/{request_ce → core}/lib/form_types.rb +4 -4
  24. data/lib/kinetic_sdk/{request_ce → core}/lib/jwt.rb +4 -4
  25. data/lib/kinetic_sdk/{request_ce → core}/lib/kapp.rb +7 -7
  26. data/lib/kinetic_sdk/{request_ce → core}/lib/meta.rb +3 -3
  27. data/lib/kinetic_sdk/{request_ce → core}/lib/oauth.rb +4 -4
  28. data/lib/kinetic_sdk/{request_ce → core}/lib/security_policy_definitions.rb +11 -11
  29. data/lib/kinetic_sdk/core/lib/space.rb +156 -0
  30. data/lib/kinetic_sdk/{request_ce → core}/lib/submissions.rb +11 -11
  31. data/lib/kinetic_sdk/{request_ce → core}/lib/system_api.rb +19 -7
  32. data/lib/kinetic_sdk/{request_ce → core}/lib/teams.rb +9 -9
  33. data/lib/kinetic_sdk/{request_ce → core}/lib/users.rb +15 -15
  34. data/lib/kinetic_sdk/{request_ce → core}/lib/webhook_jobs.rb +5 -5
  35. data/lib/kinetic_sdk/{request_ce → core}/lib/webhooks.rb +9 -9
  36. data/lib/kinetic_sdk/discussions/discussions-sdk.rb +12 -4
  37. data/lib/kinetic_sdk/discussions/lib/discussions.rb +8 -8
  38. data/lib/kinetic_sdk/discussions/lib/invitations.rb +9 -9
  39. data/lib/kinetic_sdk/discussions/lib/messages.rb +8 -8
  40. data/lib/kinetic_sdk/discussions/lib/meta.rb +1 -1
  41. data/lib/kinetic_sdk/discussions/lib/participants.rb +5 -5
  42. data/lib/kinetic_sdk/discussions/lib/related_items.rb +4 -4
  43. data/lib/kinetic_sdk/discussions/lib/websockets.rb +9 -9
  44. data/lib/kinetic_sdk/filehub/filehub-sdk.rb +11 -3
  45. data/lib/kinetic_sdk/filehub/lib/access_keys.rb +5 -5
  46. data/lib/kinetic_sdk/filehub/lib/filestores.rb +5 -5
  47. data/lib/kinetic_sdk/task/lib/access_keys.rb +35 -7
  48. data/lib/kinetic_sdk/task/lib/categories.rb +30 -17
  49. data/lib/kinetic_sdk/task/lib/config.rb +14 -14
  50. data/lib/kinetic_sdk/task/lib/engine.rb +1 -1
  51. data/lib/kinetic_sdk/task/lib/errors.rb +10 -10
  52. data/lib/kinetic_sdk/task/lib/export.rb +32 -0
  53. data/lib/kinetic_sdk/task/lib/groups.rb +23 -10
  54. data/lib/kinetic_sdk/task/lib/handlers.rb +27 -11
  55. data/lib/kinetic_sdk/task/lib/health.rb +11 -3
  56. data/lib/kinetic_sdk/task/lib/license.rb +4 -4
  57. data/lib/kinetic_sdk/task/lib/policy_rules.rb +25 -12
  58. data/lib/kinetic_sdk/task/lib/runs.rb +43 -0
  59. data/lib/kinetic_sdk/task/lib/setup.rb +2 -2
  60. data/lib/kinetic_sdk/task/lib/sources.rb +39 -8
  61. data/lib/kinetic_sdk/task/lib/tasks.rb +1 -1
  62. data/lib/kinetic_sdk/task/lib/trees.rb +84 -28
  63. data/lib/kinetic_sdk/task/lib/users.rb +6 -6
  64. data/lib/kinetic_sdk/task/task-sdk.rb +16 -4
  65. data/lib/kinetic_sdk/utils/kinetic-export-utils.rb +157 -0
  66. data/lib/kinetic_sdk/utils/kinetic-http.rb +388 -98
  67. data/lib/kinetic_sdk/utils/logger.rb +82 -46
  68. data/lib/kinetic_sdk/utils/prettier-xml-formatter.rb +60 -0
  69. data/lib/kinetic_sdk/version.rb +1 -1
  70. data/lib/kinetic_sdk.rb +5 -2
  71. metadata +41 -27
  72. data/lib/kinetic_sdk/request_ce/lib/attribute_definitions.rb +0 -153
  73. data/lib/kinetic_sdk/request_ce/lib/bridges.rb +0 -66
  74. data/lib/kinetic_sdk/request_ce/lib/space.rb +0 -89
@@ -0,0 +1,43 @@
1
+ module KineticSdk
2
+ class Task
3
+
4
+ # Delete a Run.
5
+ #
6
+ # @param id the id of the run to delete
7
+ # @param headers [Hash] hash of headers to send, default is basic authentication
8
+ # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
9
+ #
10
+ # Example
11
+ #
12
+ # delete_run(24548)
13
+ #
14
+ def delete_run(id, headers=header_basic_auth)
15
+ @logger.info("Deleting run \"#{id}\"")
16
+ delete("#{@api_url}/runs/#{id}", headers)
17
+ end
18
+
19
+ # Find runs.
20
+ #
21
+ # @param params [Hash] Query parameters that are added to the URL, such as +include+
22
+ # @param headers [Hash] hash of headers to send, default is basic authentication
23
+ # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
24
+ #
25
+ # Example
26
+ #
27
+ # find_runs({ "source" => "Kinetic Request CE" })
28
+ #
29
+ # Example
30
+ #
31
+ # find_runs({ "include" => "details" })
32
+ #
33
+ # Example
34
+ #
35
+ # find_runs({ "source" => "Kinetic Request CE", "include" => "details" })
36
+ #
37
+ def find_runs(params={}, headers=header_basic_auth)
38
+ @logger.info("Finding Runs")
39
+ get("#{@api_url}/runs", params, headers)
40
+ end
41
+
42
+ end
43
+ end
@@ -21,7 +21,7 @@ module KineticSdk
21
21
  # }
22
22
  #
23
23
  def test_db_connection(db={}, headers=default_headers)
24
- info("Testing database connection")
24
+ @logger.info("Testing database connection")
25
25
  response = post("#{@api_url}/setup/db/test", db, headers)
26
26
  response.content
27
27
  end
@@ -47,7 +47,7 @@ module KineticSdk
47
47
  # }
48
48
  #
49
49
  def migrate_db(db={}, headers=default_headers)
50
- info("Running database migrations")
50
+ @logger.info("Running database migrations")
51
51
  response = post("#{@api_url}/setup/db/migrate", db, headers)
52
52
  response.content
53
53
  end
@@ -29,7 +29,7 @@ module KineticSdk
29
29
  #
30
30
  def add_source(source, headers=default_headers)
31
31
  name = source['name']
32
- info("Adding the #{name} source")
32
+ @logger.info("Adding the #{name} source")
33
33
  post("#{@api_url}/sources", source, headers)
34
34
  end
35
35
 
@@ -39,7 +39,7 @@ module KineticSdk
39
39
  # @param headers [Hash] hash of headers to send, default is basic authentication
40
40
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
41
41
  def delete_source(name, headers=header_basic_auth)
42
- info("Deleting Source \"#{name}\"")
42
+ @logger.info("Deleting Source \"#{name}\"")
43
43
  delete("#{@api_url}/sources/#{encode(name)}", headers)
44
44
  end
45
45
 
@@ -48,19 +48,50 @@ module KineticSdk
48
48
  # @param headers [Hash] hash of headers to send, default is basic authentication
49
49
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
50
50
  def delete_sources(headers=header_basic_auth)
51
- info("Deleting all sources")
51
+ @logger.info("Deleting all sources")
52
52
  (find_sources(headers).content['sources'] || []).each do |source|
53
53
  delete("#{@api_url}/sources/#{encode(source['name'])}", headers)
54
54
  end
55
55
  end
56
56
 
57
+ # Export all sources to :source-slug.json file in export_directory/sources
58
+ #
59
+ # @param headers [Hash] hash of headers to send, default is basic authentication
60
+ # @return nil
61
+ def export_sources(headers=header_basic_auth)
62
+ raise StandardError.new "An export directory must be defined to export sources." if @options[:export_directory].nil?
63
+ response = find_sources({"include" => "policyRules"})
64
+ (response.content["sourceRoots"] || []).each do |source|
65
+ # determine which directory to write the file to
66
+ if source['name'] != "-"
67
+ # create the directory if it doesn't yet exist
68
+ sources_dir = FileUtils::mkdir_p(File.join(@options[:export_directory], "sources"))
69
+ source_file = File.join(sources_dir, "#{source['name'].slugify}.json")
70
+ write_object_to_file(source_file, source)
71
+ end
72
+ end
73
+ end
74
+
75
+ # Import all sources from :source-slug.json file in export_directory/sources
76
+ #
77
+ # @param headers [Hash] hash of headers to send, default is basic authentication
78
+ # @return nil
79
+ def import_sources(headers=default_headers)
80
+ raise StandardError.new "An export directory must be defined to import sources." if @options[:export_directory].nil?
81
+ @logger.info("Importing all Sources in Export Directory")
82
+ Dir["#{@options[:export_directory]}/sources/*.json"].sort.each do |file|
83
+ source = JSON.parse(File.read(file))
84
+ add_source(source, headers)
85
+ end
86
+ end
87
+
57
88
  # Find all sources
58
89
  #
59
90
  # @param params [Hash] Query parameters that are added to the URL, such as +include+
60
91
  # @param headers [Hash] hash of headers to send, default is basic authentication
61
92
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
62
93
  def find_sources(params={}, headers=header_basic_auth)
63
- info("Finding all sources")
94
+ @logger.info("Finding all sources")
64
95
  get("#{@api_url}/sources", params, headers)
65
96
  end
66
97
 
@@ -71,7 +102,7 @@ module KineticSdk
71
102
  # @param headers [Hash] hash of headers to send, default is basic authentication
72
103
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
73
104
  def find_source(name, params={}, headers=header_basic_auth)
74
- info("Finding source named \"#{name}\"")
105
+ @logger.info("Finding source named \"#{name}\"")
75
106
  get("#{@api_url}/sources/#{encode(name)}", params, headers)
76
107
  end
77
108
 
@@ -101,7 +132,7 @@ module KineticSdk
101
132
  # )
102
133
  #
103
134
  def update_source(source, body={}, headers=default_headers)
104
- info("Updating the \"#{source['name']}\" Source")
135
+ @logger.info("Updating the \"#{source['name']}\" Source")
105
136
  put("#{@api_url}/sources/#{encode(source['name'])}", body, headers)
106
137
  end
107
138
 
@@ -114,7 +145,7 @@ module KineticSdk
114
145
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
115
146
  def add_policy_rule_to_source(policy_rule_type, policy_rule_name, source_name, headers=default_headers)
116
147
  body = { "type" => policy_rule_type, "name" => policy_rule_name }
117
- info("Adding policy rule \"#{policy_rule_type} - #{policy_rule_name}\" to source \"#{source_name}\"")
148
+ @logger.info("Adding policy rule \"#{policy_rule_type} - #{policy_rule_name}\" to source \"#{source_name}\"")
118
149
  post("#{@api_url}/sources/#{encode(source_name)}/policyRules", body, headers)
119
150
  end
120
151
 
@@ -126,7 +157,7 @@ module KineticSdk
126
157
  # @param headers [Hash] hash of headers to send, default is basic authentication and accept JSON content type
127
158
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
128
159
  def remove_policy_rule_from_source(policy_rule_type, policy_rule_name, source_name, headers=default_headers)
129
- info("Removing policy rule \"#{policy_rule_type} - #{policy_rule_name}\" from source \"#{source_name}\"")
160
+ @logger.info("Removing policy rule \"#{policy_rule_type} - #{policy_rule_name}\" from source \"#{source_name}\"")
130
161
  delete("#{@api_url}/sources/#{encode(source_name)}/policyRules/#{encode(policy_rule_type)}/#{encode(policy_rule_name)}", headers)
131
162
  end
132
163
 
@@ -9,7 +9,7 @@ module KineticSdk
9
9
  # @param headers [Hash] hash of headers to send, default is basic authentication and accept JSON content type
10
10
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
11
11
  def complete_deferred_task(source_name, body, headers=default_headers)
12
- info("Completing deferred task for the \"#{source_name}\" Source.")
12
+ @logger.info("Completing deferred task for the \"#{source_name}\" Source.")
13
13
  post("#{@api_v1_url}/complete-deferred-task/#{encode(source_name)}", body, headers)
14
14
  end
15
15
 
@@ -25,7 +25,7 @@ module KineticSdk
25
25
  else
26
26
  title = "#{tree.to_s}"
27
27
  end
28
- info("Deleting Tree \"#{title}\"")
28
+ @logger.info("Deleting Tree \"#{title}\"")
29
29
  delete("#{@api_url}/trees/#{encode(title)}", headers)
30
30
  end
31
31
 
@@ -44,15 +44,15 @@ module KineticSdk
44
44
  #
45
45
  def delete_trees(source_name=nil, headers=header_basic_auth)
46
46
  if source_name.nil?
47
- info("Deleting all trees")
47
+ @logger.info("Deleting all trees")
48
48
  params = {}
49
49
  else
50
- info("Deleting trees for Source \"#{source_name}\"")
50
+ @logger.info("Deleting trees for Source \"#{source_name}\"")
51
51
  params = { "source" => source_name }
52
52
  end
53
53
 
54
54
  (find_trees(params, headers).content['trees'] || []).each do |tree|
55
- info("Deleting tree \"#{tree['title']}\"")
55
+ @logger.info("Deleting tree \"#{tree['title']}\"")
56
56
  delete("#{@api_url}/trees/#{encode(tree['title'])}", headers)
57
57
  end
58
58
  end
@@ -69,7 +69,7 @@ module KineticSdk
69
69
  # find_trees({ "source" => "Kinetic Request CE" })
70
70
  #
71
71
  # Example
72
- #
72
+ #
73
73
  # find_trees({ "include" => "details" })
74
74
  #
75
75
  # Example
@@ -77,7 +77,7 @@ module KineticSdk
77
77
  # find_trees({ "source" => "Kinetic Request CE", "include" => "details" })
78
78
  #
79
79
  def find_trees(params={}, headers=header_basic_auth)
80
- info("Finding Trees")
80
+ @logger.info("Finding Trees")
81
81
  get("#{@api_url}/trees", params, headers)
82
82
  end
83
83
 
@@ -100,7 +100,7 @@ module KineticSdk
100
100
  # find_routines({ "source" => "Kinetic Request CE", "include" => "details" })
101
101
  #
102
102
  def find_routines(params={}, headers=header_basic_auth)
103
- info("Finding Routines")
103
+ @logger.info("Finding Routines")
104
104
  response = get("#{@api_url}/trees", params, headers)
105
105
 
106
106
  routines = []
@@ -127,10 +127,30 @@ module KineticSdk
127
127
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
128
128
  def import_tree(tree, force_overwrite=false, headers=header_basic_auth)
129
129
  body = { "content" => tree }
130
- info("Importing Tree #{File.basename(tree)}")
130
+ @logger.info("Importing Tree #{File.basename(tree)}")
131
131
  post_multipart("#{@api_url}/trees?force=#{force_overwrite}", body, headers)
132
132
  end
133
133
 
134
+ # Import trees
135
+ #
136
+ # If the trees already exists on the server, this will fail unless forced
137
+ # to overwrite.
138
+ #
139
+ # The source named in the trees content must also exist on the server, or
140
+ # the import will fail.
141
+ #
142
+ # @param force_overwrite [Boolean] whether to overwrite a tree if it exists, default is false
143
+ # @param headers [Hash] hash of headers to send, default is basic authentication
144
+ # @return nil
145
+ def import_trees(force_overwrite=false, headers=header_basic_auth)
146
+ raise StandardError.new "An export directory must be defined to import trees from." if @options[:export_directory].nil?
147
+ @logger.info("Importing all Trees from Export Directory")
148
+ Dir["#{@options[:export_directory]}/sources/**/*.xml"].sort.each do |file|
149
+ tree_file = File.new(file, "rb")
150
+ import_tree(tree_file, force_overwrite, headers)
151
+ end
152
+ end
153
+
134
154
  # Import a routine
135
155
  #
136
156
  # If the routine already exists on the server, this will fail unless
@@ -142,10 +162,27 @@ module KineticSdk
142
162
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
143
163
  def import_routine(routine, force_overwrite=false, headers=header_basic_auth)
144
164
  body = { "content" => routine }
145
- info("Importing Routine #{File.basename(routine)}")
165
+ @logger.info("Importing Routine #{File.basename(routine)}")
146
166
  post_multipart("#{@api_url}/trees?force=#{force_overwrite}", body, headers)
147
167
  end
148
168
 
169
+ # Import routines
170
+ #
171
+ # If the routines already exists on the server, this will fail unless forced
172
+ # to overwrite.
173
+ #
174
+ # @param force_overwrite [Boolean] whether to overwrite routines if they exist, default is false
175
+ # @param headers [Hash] hash of headers to send, default is basic authentication
176
+ # @return nil
177
+ def import_routines(force_overwrite=false, headers=header_basic_auth)
178
+ raise StandardError.new "An export directory must be defined to import trees from." if @options[:export_directory].nil?
179
+ @logger.info("Importing all Routines from Export Directory")
180
+ Dir["#{@options[:export_directory]}/routines/*.xml"].sort.each do |file|
181
+ routine_file = File.new(file, "rb")
182
+ import_routine(routine_file, force_overwrite, headers)
183
+ end
184
+ end
185
+
149
186
  # Find a single tree by title (Source Name :: Group Name :: Tree Name)
150
187
  #
151
188
  # @param title [String] The tree title
@@ -161,7 +198,7 @@ module KineticSdk
161
198
  # )
162
199
  #
163
200
  def find_tree(title, params={}, headers=header_basic_auth)
164
- info("Finding the \"#{title}\" Tree")
201
+ @logger.info("Finding the \"#{title}\" Tree")
165
202
  get("#{@api_url}/trees/#{encode(title)}", params, headers)
166
203
  end
167
204
 
@@ -169,11 +206,11 @@ module KineticSdk
169
206
  #
170
207
  # @param title [String] the title of the tree or routine
171
208
  # @param headers [Hash] hash of headers to send, default is basic authentication
172
- # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
209
+ # @return nil
173
210
  #
174
211
  def export_tree(title, headers=header_basic_auth)
175
212
  raise StandardError.new "An export directory must be defined to export a tree." if @options[:export_directory].nil?
176
- info("Exporting tree \"#{title}\" to #{@options[:export_directory]}.")
213
+ @logger.info("Exporting tree \"#{title}\" to #{@options[:export_directory]}.")
177
214
  # Get the tree
178
215
  response = find_tree(title, { "include" => "export" })
179
216
  # Parse the response and export the tree
@@ -186,12 +223,21 @@ module KineticSdk
186
223
  tree_file = File.join(routine_dir, "#{tree['name'].slugify}.xml")
187
224
  else
188
225
  # Create the directory if it doesn't yet exist
189
- tree_dir = FileUtils::mkdir_p(File.join(@options[:export_directory], "trees", tree['sourceName'].slugify))
190
- tree_file = File.join(tree_dir, "#{tree['sourceName'].slugify}.#{tree['sourceGroup'].slugify}.#{tree['name'].slugify}.xml")
226
+ tree_dir = FileUtils::mkdir_p(File.join(@options[:export_directory],"sources", tree['sourceName'].slugify , "trees"))
227
+ tree_file = File.join(tree_dir, "#{tree['sourceGroup'].slugify}.#{tree['name'].slugify}.xml")
191
228
  end
229
+
192
230
  # write the file
193
- File.write(tree_file, tree['export'])
194
- info("Exported #{tree['type']}: #{tree['title']} to #{tree_file}")
231
+ server_version = server_info(headers).content["version"]
232
+ if server_version > "04.03.0z"
233
+ File.write(tree_file, tree['export'])
234
+ else
235
+ xml_doc = REXML::Document.new(tree["export"])
236
+ xml_doc.context[:attribute_quote] = :quote
237
+ xml_formatter = Prettier.new
238
+ xml_formatter.write(xml_doc, File.open(tree_file, "w"))
239
+ end
240
+ @logger.info("Exported #{tree['type']}: #{tree['title']} to #{tree_file}")
195
241
  end
196
242
 
197
243
  # Export all trees and local routines for a source, and global routines
@@ -200,19 +246,20 @@ module KineticSdk
200
246
  # - Leave blank or pass nil to export all trees and global routines
201
247
  # - Pass "-" to export only global routines
202
248
  # @param headers [Hash] hash of headers to send, default is basic authentication
203
- # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
249
+ # @return nil
204
250
  def export_trees(source_name=nil, headers=header_basic_auth)
205
251
  raise StandardError.new "An export directory must be defined to export trees." if @options[:export_directory].nil?
206
252
  if source_name.nil?
207
- info("Exporting all trees and routines to #{@options[:export_directory]}.")
208
- (find_sources.content["sourceRoots"] || []).each do |sourceRoot|
253
+ @logger.info("Exporting all trees and routines to #{@options[:export_directory]}.")
254
+ export_routines(headers)
255
+ (find_sources({}, headers).content["sourceRoots"] || []).each do |sourceRoot|
209
256
  export_trees(sourceRoot['name'])
210
257
  end
211
258
  return
212
259
  elsif source_name == "-"
213
- info("Exporting global routines to #{@options[:export_directory]}.")
260
+ @logger.info("Exporting global routines to #{@options[:export_directory]}.")
214
261
  else
215
- info("Exporting trees and routines for source \"#{source_name}\" to #{@options[:export_directory]}.")
262
+ @logger.info("Exporting trees and routines for source \"#{source_name}\" to #{@options[:export_directory]}.")
216
263
  end
217
264
 
218
265
  # Get all the trees and routines for the source
@@ -226,12 +273,21 @@ module KineticSdk
226
273
  tree_file = File.join(routine_dir, "#{tree['name'].slugify}.xml")
227
274
  else
228
275
  # create the directory if it doesn't yet exist
229
- tree_dir = FileUtils::mkdir_p(File.join(@options[:export_directory], "trees", source_name.slugify))
230
- tree_file = File.join(tree_dir, "#{source_name.slugify}.#{tree['sourceGroup'].slugify}.#{tree['name'].slugify}.xml")
276
+ tree_dir = FileUtils::mkdir_p(File.join(@options[:export_directory], "sources", source_name.slugify ,"trees"))
277
+ tree_file = File.join(tree_dir, "#{tree['sourceGroup'].slugify}.#{tree['name'].slugify}.xml")
231
278
  end
279
+
232
280
  # write the file
233
- File.write(tree_file, tree['export'])
234
- info("Exported #{tree['type']}: #{tree['title']} to #{tree_file}")
281
+ server_version = server_info(headers).content["version"]
282
+ if server_version > "04.03.0z"
283
+ File.write(tree_file, tree['export'])
284
+ else
285
+ xml_doc = REXML::Document.new(tree["export"])
286
+ xml_doc.context[:attribute_quote] = :quote
287
+ xml_formatter = Prettier.new
288
+ xml_formatter.write(xml_doc, File.open(tree_file, "w"))
289
+ end
290
+ @logger.info("Exported #{tree['type']}: #{tree['title']} to #{tree_file}")
235
291
  end
236
292
  end
237
293
 
@@ -239,7 +295,7 @@ module KineticSdk
239
295
  # Export all global routines
240
296
  #
241
297
  # @param headers [Hash] hash of headers to send, default is basic authentication
242
- # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
298
+ # @return nil
243
299
  def export_routines(headers=header_basic_auth)
244
300
  export_trees("-", headers)
245
301
  end
@@ -252,7 +308,7 @@ module KineticSdk
252
308
  # @param headers [Hash] hash of headers to send, default is basic authentication and accept JSON content type
253
309
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
254
310
  def run_tree(title, body={}, headers=default_headers)
255
- info("Running tree #{title}")
311
+ @logger.info("Running tree #{title}")
256
312
  parts = title.split(" :: ")
257
313
  raise StandardError.new "Title is invalid: #{title}" if parts.size != 3
258
314
  url = "#{@api_v1_url}/run-tree/#{encode(parts[0])}/#{encode(parts[1])}/#{encode(parts[2])}"
@@ -266,7 +322,7 @@ module KineticSdk
266
322
  # @param headers [Hash] hash of headers to send, default is basic authentication and accept JSON content type
267
323
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
268
324
  def update_tree(title, body={}, headers=default_headers)
269
- info("Updating the \"#{title}\" Tree")
325
+ @logger.info("Updating the \"#{title}\" Tree")
270
326
  put("#{@api_url}/trees/#{encode(title)}", body, headers)
271
327
  end
272
328
 
@@ -16,7 +16,7 @@ module KineticSdk
16
16
  # })
17
17
  #
18
18
  def add_user(user, headers=default_headers)
19
- info("Add user \"#{user['loginId']}\"")
19
+ @logger.info("Add user \"#{user['loginId']}\"")
20
20
  post("#{@api_url}/users", user, headers)
21
21
  end
22
22
 
@@ -26,7 +26,7 @@ module KineticSdk
26
26
  # @param headers [Hash] hash of headers to send, default is basic authentication
27
27
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
28
28
  def delete_user(login_id, headers=header_basic_auth)
29
- info("Deleting User \"#{login_id}\"")
29
+ @logger.info("Deleting User \"#{login_id}\"")
30
30
  delete("#{@api_url}/users/#{encode(login_id)}", headers)
31
31
  end
32
32
 
@@ -35,9 +35,9 @@ module KineticSdk
35
35
  # @param headers [Hash] hash of headers to send, default is basic authentication
36
36
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
37
37
  def delete_users(headers=header_basic_auth)
38
- info("Deleting all users")
38
+ @logger.info("Deleting all users")
39
39
  (find_users(headers).content["users"] || []).each do |user|
40
- delete("#{@api_url}/users/#{encode(user['login_id'])}", headers)
40
+ delete_user(user['loginId'], headers)
41
41
  end
42
42
  end
43
43
 
@@ -47,7 +47,7 @@ module KineticSdk
47
47
  # @param headers [Hash] hash of headers to send, default is basic authentication
48
48
  # @return [KineticSdk::Utils::KineticHttpResponse] object, with +code+, +message+, +content_string+, and +content+ properties
49
49
  def find_users(params={}, headers=header_basic_auth)
50
- info("Finding all users")
50
+ @logger.info("Finding all users")
51
51
  get("#{@api_url}/users", params, headers)
52
52
  end
53
53
 
@@ -67,7 +67,7 @@ module KineticSdk
67
67
  # })
68
68
  #
69
69
  def update_user(login_id, user, headers=default_headers)
70
- info("Updating user \"#{login_id}\"")
70
+ @logger.info("Updating user \"#{login_id}\"")
71
71
  put("#{@api_url}/users/#{encode(login_id)}", user, headers)
72
72
  end
73
73
 
@@ -10,7 +10,11 @@ module KineticSdk
10
10
  # Include the KineticHttpUtils module
11
11
  include KineticSdk::Utils::KineticHttpUtils
12
12
 
13
- attr_reader :api_url, :api_v1_url, :config_user, :options, :server, :version, :username, :password
13
+ # Include the KineticExportUtils module
14
+ include KineticSdk::Utils::KineticExportUtils
15
+
16
+ attr_reader :api_url, :api_v1_url, :config_user, :options, :server,
17
+ :version, :username, :password, :logger
14
18
 
15
19
  # Initalize the Task SDK with the web server URL and user credentials,
16
20
  # along with any custom option values.
@@ -28,9 +32,12 @@ module KineticSdk
28
32
  # @option opts [String] :password the password for the user
29
33
  # @option opts [Hash<Symbol, Object>] :options ({}) optional settings
30
34
  #
31
- # * :export_directory (String) (_example: /opt/exports/kinetic-task) directory to write files when exporting,
32
- # * :log_level (String) (_defaults to: off_) level of logging - off | info | debug | trace
33
- # * :max_redirects (Fixnum) (_defaults to: 10_) maximum number of redirects to follow
35
+ # * :export_directory (String) (_example: /opt/exports/kinetic-task_) directory to write files when exporting,
36
+ # * :gateway_retry_limit (FixNum) (_defaults to: 5_) max number of times to retry a bad gateway
37
+ # * :gateway_retry_delay (Float) (_defaults to: 1.0_) number of seconds to delay before retrying a bad gateway
38
+ # * :log_level (String) (_defaults to: off_) level of logging - off | error | warn | info | debug
39
+ # * :log_output (String) (_defaults to: STDOUT_) where to send output - STDOUT | STDERR
40
+ # * :max_redirects (Fixnum) (_defaults to: 5_) maximum number of redirects to follow
34
41
  # * :ssl_ca_file (String) full path to PEM certificate used to verify the server
35
42
  # * :ssl_verify_mode (String) (_defaults to: none_) - none | peer
36
43
  #
@@ -73,6 +80,11 @@ module KineticSdk
73
80
 
74
81
  # process any individual options
75
82
  @options = options.delete(:options) || {}
83
+ # setup logging
84
+ log_level = @options[:log_level] || @options["log_level"]
85
+ log_output = @options[:log_output] || @options["log_output"]
86
+ @logger = KineticSdk::Utils::KLogger.new(log_level, log_output)
87
+
76
88
  @config_user[:username] = options[:username]
77
89
  @config_user[:password] = options[:password]
78
90
  @server = options[:app_server_url].chomp('/')
@@ -0,0 +1,157 @@
1
+ module KineticSdk
2
+ module Utils
3
+
4
+ # The KineticExportUtils module provides methods to simplify exporting
5
+ # objects and writing to the local file system.
6
+ module KineticExportUtils
7
+
8
+ # Builds the tree structure of the export including the arguments
9
+ #
10
+ # @param args [Array] list of property names to include in the export:
11
+ # (i.e. slug, name, etc)
12
+ # @return [Hash] struture of the shape to be exported
13
+ def prepare_shape(*args)
14
+ shape = {}
15
+ args.each do |arg|
16
+ segments = arg.split('.')
17
+ pointer = shape
18
+ segments.each do |segment|
19
+ if segment =~ /\{(.*)\}/
20
+ pointer[:variable] ||= $1
21
+ pointer[$1] ||= {}
22
+ pointer = pointer[$1]
23
+ else
24
+ pointer[segment] ||= {}
25
+ pointer = pointer[segment]
26
+ end
27
+ end
28
+ end
29
+ shape
30
+ end
31
+
32
+ # Determines if the current path should be extracted further
33
+ #
34
+ # @param export_path [String] the path in which to determine if further extraction should occur
35
+ # @param export_shape [Hash] the directory and file structure of how the data should be written
36
+ # @return [Boolean] true if the path should be extracted further, otherwise false
37
+ def should_extract(export_path, export_shape)
38
+ # Prepare the metadata
39
+ export_path_segments = export_path.split('.')
40
+ pointer = export_shape
41
+ result = true
42
+ # Walk the export path
43
+ export_path_segments.each do |export_path_segment|
44
+ # If the object path corresponds to a "variable"
45
+ if pointer.has_key?(:variable)
46
+ pointer = pointer[pointer[:variable]]
47
+ # If the object path corresponds to a static property
48
+ else
49
+ pointer = pointer[export_path_segment]
50
+ end
51
+ # If the pointer is null (indicating that the property should not be extracted)
52
+ if pointer.nil?
53
+ # Break out of the loop
54
+ result = false
55
+ break
56
+ end
57
+ end
58
+ # Return the result
59
+ result
60
+ end
61
+
62
+ # Fetches the variable property of a given path (ie slug, name, etc)
63
+ #
64
+ # @param export_shape [Hash] the directory and file structure of how the data should be written
65
+ # @param object_path [String] the path in which to get the variable property from
66
+ # @return [String] the value of the variable property, or nil if it doesn't exist
67
+ def get_variable_property(export_shape, object_path)
68
+ # Prepare the metadata
69
+ object_path_segments = object_path.split('.')
70
+ pointer = export_shape
71
+ # Walk the object path
72
+ object_path_segments.each do |object_path_segment|
73
+ # If the object path corresponds to a "variable"
74
+ if pointer.has_key?(:variable)
75
+ pointer = pointer[pointer[:variable]]
76
+ # If the object path corresponds to a static property
77
+ else
78
+ pointer = pointer[object_path_segment]
79
+ end
80
+ # If the pointer is null (indicating that the property should not be extracted)
81
+ break if pointer.nil?
82
+ end
83
+ # Return the result
84
+ pointer.nil? ? nil : pointer[:variable]
85
+ end
86
+
87
+ # Creates directory structure and writes file
88
+ #
89
+ # @param filename [String] the full path and name of the file to be written
90
+ # @param file_contents [String] the content of the file to be written
91
+ # @return nil
92
+ def write_object_to_file(filename, file_contents)
93
+ # Create Folder if not exists
94
+ dir_path = File.dirname(filename)
95
+ FileUtils.mkdir_p(dir_path, :mode => 0700)
96
+ # Write File
97
+ File.open(filename, 'w') { |file| file.write(JSON.pretty_generate(file_contents)) }
98
+ end
99
+
100
+ # Processes and writes data exported from the core service
101
+ #
102
+ # @param core_path [String] the root folder path to write the data to
103
+ # @param export_shape [Hash] the directory and file structure of how the data should be written
104
+ # @param object [Hash] the object being processed
105
+ # @param object_path [String] the path of the object being processed (used recursively)
106
+ # @return nil
107
+ def process_export(core_path, export_shape, object, object_path='')
108
+ # Prepare metadata
109
+ child_objects = {}
110
+ file_contents = {}
111
+ if object.kind_of?(Array)
112
+ file_contents = object
113
+ else
114
+ # For each of the object properties
115
+ object.each do |key, value|
116
+ # Build child object path
117
+ child_object_path = object_path.empty? ? key : "#{object_path}.#{key}"
118
+
119
+ # If the property should be extracted into its own folder/file
120
+ if should_extract(child_object_path, export_shape)
121
+ if value.kind_of?(Array)
122
+ variable = get_variable_property(export_shape, child_object_path)
123
+ if variable.nil?
124
+ child_objects[child_object_path] = value
125
+ else
126
+ value.each do |item|
127
+ child_objects["#{child_object_path}.#{item[variable]}"] = item
128
+ end
129
+ end
130
+ else
131
+ child_objects[child_object_path] = value
132
+ end
133
+ # If the property does not need to be extracted
134
+ else
135
+ # Add the property to the file contents
136
+ file_contents[key] = value
137
+ end
138
+ end
139
+ end
140
+
141
+ # If this is not the "root" object
142
+ if object_path != '' && !file_contents.empty?
143
+ # Write the file_contents based upon the
144
+ filename = "#{core_path}/#{object_path.gsub('.', '/')}.json"
145
+ write_object_to_file(filename, file_contents)
146
+ end
147
+
148
+ # For each of the child objects
149
+ child_objects.each do |key, child_object|
150
+ # Process the export for that object (recursively)
151
+ process_export(core_path, export_shape, child_object, key)
152
+ end
153
+ end
154
+
155
+ end
156
+ end
157
+ end