kinetic_sdk 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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