k_manager 0.0.13 → 0.0.28
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/Gemfile +23 -0
- data/Rakefile +2 -0
- data/docs/flow.drawio +16 -0
- data/exe/k_manager +19 -0
- data/hooks/update-version +1 -1
- data/k_manager.gemspec +9 -0
- data/lib/k_manager/area.rb +49 -0
- data/lib/k_manager/cli/base_command.rb +23 -0
- data/lib/k_manager/cli/commands.rb +25 -0
- data/lib/k_manager/cli/info.rb +81 -0
- data/lib/k_manager/cli/new.rb +130 -0
- data/lib/k_manager/cli/version.rb +15 -0
- data/lib/k_manager/cli/watch.rb +65 -0
- data/lib/k_manager/document_factory.rb +81 -0
- data/lib/k_manager/manager.rb +158 -0
- data/lib/k_manager/overview/dashboard.rb +197 -0
- data/lib/k_manager/overview/dump_json.rb +35 -0
- data/lib/k_manager/overview/models.rb +76 -0
- data/lib/k_manager/overview/queries.rb +53 -0
- data/lib/k_manager/resources/base_resource.rb +203 -52
- data/lib/k_manager/resources/file_resource.rb +81 -58
- data/lib/k_manager/resources/{ruby_file_resource.rb → file_resources/ruby_file_resource.rb} +0 -0
- data/lib/k_manager/resources/{unknown_file_resource.rb → file_resources/unknown_file_resource.rb} +0 -0
- data/lib/k_manager/resources/mem_resource.rb +17 -0
- data/lib/k_manager/resources/resource_document_factory.rb +123 -0
- data/lib/k_manager/resources/resource_factory.rb +28 -0
- data/lib/k_manager/resources/resource_manager.rb +201 -0
- data/lib/k_manager/resources/resource_set.rb +90 -0
- data/lib/k_manager/resources/web_resource.rb +113 -0
- data/lib/k_manager/version.rb +1 -1
- data/lib/k_manager/watcher.rb +113 -0
- data/lib/k_manager/{x_project.rb → x_resource_documents/x_project.rb} +0 -0
- data/lib/k_manager/{x_project_manager.rb → x_resource_documents/x_project_manager.rb} +0 -0
- data/lib/k_manager/{x_register.rb → x_resource_documents/x_register.rb} +0 -0
- data/lib/k_manager.rb +111 -24
- data/tasks/watch.rake +18 -0
- metadata +118 -25
- data/Assessment1.md +0 -127
- data/Assessment2.md +0 -88
- data/lib/k_manager/configuration/project_config.rb +0 -14
- data/lib/k_manager/create_document.rb +0 -31
- data/lib/k_manager/documents/basic_document.rb +0 -21
- data/lib/k_manager/documents/builder_document.rb +0 -18
- data/lib/k_manager/documents/document_taggable.rb +0 -94
- data/lib/k_manager/documents/model_document.rb +0 -19
- data/lib/k_manager/project.rb +0 -50
- data/lib/k_manager/resources/csv_file_resource.rb +0 -27
- data/lib/k_manager/resources/factories/document_factory.rb +0 -52
- data/lib/k_manager/resources/json_file_resource.rb +0 -22
- data/lib/k_manager/resources/yaml_file_resource.rb +0 -21
@@ -5,6 +5,8 @@ module KManager
|
|
5
5
|
# A resource represents text based content in the project. The content
|
6
6
|
# maybe data, interpreted ruby code or a combination of the two.
|
7
7
|
#
|
8
|
+
# Any non-binary file that is useful for processing.
|
9
|
+
#
|
8
10
|
# Currently resources refer to file based content, but it is envisaged
|
9
11
|
# that resources could come from a distributed source such as Gist,
|
10
12
|
# WebService, or even FTP.
|
@@ -21,9 +23,21 @@ module KManager
|
|
21
23
|
# generally only one document.
|
22
24
|
class BaseResource
|
23
25
|
include KLog::Logging
|
26
|
+
include KDoc::Guarded
|
27
|
+
|
28
|
+
ACTIONS = %i[load_content register_document load_document].freeze
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def valid_action?(action)
|
32
|
+
ACTIONS.include?(action)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :uri # https://ruby-doc.org/stdlib-2.6.1/libdoc/uri/rdoc/URI/Generic.html
|
24
37
|
|
38
|
+
# TODO: Refactor from status to state and extract to a State class
|
25
39
|
# Status of the resource
|
26
|
-
# - :
|
40
|
+
# - :alive (i am alive, or instantiated)
|
27
41
|
# - :content_loading
|
28
42
|
# - :content_loaded
|
29
43
|
# - :documents_registering
|
@@ -32,17 +46,25 @@ module KManager
|
|
32
46
|
# - :documents_loaded
|
33
47
|
attr_reader :status
|
34
48
|
|
35
|
-
#
|
49
|
+
# What content type does the underlying resource type generally contain
|
36
50
|
#
|
37
|
-
#
|
38
|
-
attr_reader :source
|
39
|
-
|
40
|
-
# Where is the type of the
|
51
|
+
# Examples:
|
41
52
|
#
|
42
|
-
#
|
43
|
-
|
53
|
+
# :csv - CSV text content
|
54
|
+
# :json - JSON text content
|
55
|
+
# :yaml - YAML text content
|
56
|
+
# :xml - XML text content
|
57
|
+
# :ruby - Ruby code file of unknown capability
|
58
|
+
# :ruby_dsl - Ruby code holding some type of known DSL such as a KDoc
|
59
|
+
# DISCUSS: should this subtype be delegated to an attribute on a responsible class
|
60
|
+
attr_reader :content_type
|
61
|
+
|
62
|
+
# TODO: Write Test
|
63
|
+
# Area is an option property what will only be set when working with Area
|
64
|
+
attr_accessor :area
|
44
65
|
|
45
|
-
|
66
|
+
# Optional namespace that the resource belongs to.
|
67
|
+
attr_reader :namespace
|
46
68
|
|
47
69
|
# Content of resource, use read content to load this property
|
48
70
|
attr_reader :content
|
@@ -60,40 +82,70 @@ module KManager
|
|
60
82
|
#
|
61
83
|
# @param [Hash] **opts Options for initializing the resource
|
62
84
|
# @option opts [Project] :project attach the resource to a project
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@type = :unknown
|
85
|
+
# NAMESPACE can probably be taken from file set relative path
|
86
|
+
def initialize(uri, **opts)
|
87
|
+
self.uri = uri
|
67
88
|
|
68
|
-
|
89
|
+
@status = :alive
|
90
|
+
@area = value_remove(opts, :area)
|
91
|
+
@namespace = value_remove(opts, :namespace)
|
92
|
+
@content_type = @content_type || value_remove(opts, :content_type) || infer_content_type || default_content_type
|
93
|
+
@content = value_remove(opts, :content)
|
94
|
+
|
95
|
+
# attach_project(opts[:project]) if opts[:project]
|
69
96
|
@documents = []
|
70
97
|
end
|
71
98
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
self
|
99
|
+
def source_path
|
100
|
+
# Expectation that uri is of type URI::HTTP or URI::HTTPS
|
101
|
+
uri.to_s
|
76
102
|
end
|
77
103
|
|
104
|
+
# TODO: Is this really needed?
|
78
105
|
def document
|
79
106
|
@document ||= documents&.first
|
80
107
|
end
|
81
108
|
|
109
|
+
def activated?
|
110
|
+
# log.section_heading("Am I activated?")
|
111
|
+
# log.kv 'URI', uri
|
112
|
+
# log.kv 'ACTIVE URI', self.area.manager.active_uri
|
113
|
+
return false if area.nil?
|
114
|
+
|
115
|
+
uri.to_s == area.manager.active_uri.to_s
|
116
|
+
end
|
117
|
+
|
82
118
|
# Fire actions and keep track of status as they fire
|
83
119
|
#
|
84
120
|
# @param [Symbol] action what action is to be fired
|
85
121
|
# - :load_content for loading text content
|
86
122
|
# - :register_document for registering 1 or more documents (name and namespace) against the resource
|
87
123
|
# - :load_document for parsing the content into a document
|
124
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
88
125
|
def fire_action(action)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
126
|
+
# TODO: Write test for valid
|
127
|
+
return unless valid?
|
128
|
+
|
129
|
+
case action
|
130
|
+
when :load_content
|
131
|
+
load_content_action if alive?
|
132
|
+
when :register_document
|
133
|
+
register_document_action if content_loaded?
|
134
|
+
when :load_document
|
135
|
+
load_document_action if documents_registered?
|
95
136
|
else
|
96
|
-
|
137
|
+
log.warn "Action: '#{action}' is invalid for status: '#{status}'"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
141
|
+
|
142
|
+
def fire_next_action
|
143
|
+
if alive?
|
144
|
+
fire_action(:load_content)
|
145
|
+
elsif content_loaded?
|
146
|
+
fire_action(:register_document)
|
147
|
+
elsif documents_registered?
|
148
|
+
fire_action(:load_document)
|
97
149
|
end
|
98
150
|
end
|
99
151
|
|
@@ -106,60 +158,159 @@ module KManager
|
|
106
158
|
end
|
107
159
|
|
108
160
|
def load_content
|
109
|
-
log.warn 'you need to implement load_content'
|
161
|
+
# log.warn 'you need to implement load_content'
|
110
162
|
end
|
111
163
|
|
112
164
|
def register_document
|
113
|
-
log.warn 'you need to implement register_document'
|
165
|
+
# log.warn 'you need to implement register_document'
|
166
|
+
KManager::Resources::ResourceDocumentFactory.create_documents(self)
|
114
167
|
end
|
115
168
|
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
169
|
+
# rubocop:disable Lint/RescueException
|
170
|
+
def load_document
|
171
|
+
# log.warn 'you need to implement register_document'
|
172
|
+
documents.each do |document|
|
173
|
+
document.execute_block(run_actions: activated?)
|
174
|
+
end
|
175
|
+
rescue Exception => e
|
176
|
+
guard(e.message)
|
177
|
+
debug
|
178
|
+
log.exception(e, style: KManager.opts.exception_style)
|
179
|
+
# log.exception(e, style: :short)
|
180
|
+
end
|
181
|
+
# rubocop:enable Lint/RescueException
|
182
|
+
|
183
|
+
# This is when you need a simple container
|
184
|
+
def new_document(data)
|
185
|
+
document = KDoc::Container.new(
|
120
186
|
key: infer_key,
|
121
|
-
type:
|
122
|
-
namespace:
|
123
|
-
|
187
|
+
type: content_type,
|
188
|
+
namespace: namespace,
|
189
|
+
default_data_type: data.class,
|
190
|
+
data: data
|
124
191
|
)
|
192
|
+
attach_document(document)
|
193
|
+
end
|
194
|
+
|
195
|
+
def attach_document(document, change_content_type: nil)
|
196
|
+
@content_type = change_content_type if change_content_type
|
197
|
+
|
198
|
+
document.owner = self
|
199
|
+
@documents << document
|
200
|
+
document
|
125
201
|
end
|
126
202
|
|
127
|
-
|
128
|
-
|
129
|
-
|
203
|
+
def scheme
|
204
|
+
uri&.scheme&.to_sym || default_scheme
|
205
|
+
end
|
130
206
|
|
131
|
-
|
207
|
+
def host
|
208
|
+
uri&.host
|
132
209
|
end
|
133
210
|
|
134
|
-
|
135
|
-
|
211
|
+
# What schema does the underlying resource connect with by default
|
212
|
+
#
|
213
|
+
# Examples:
|
214
|
+
#
|
215
|
+
# :file
|
216
|
+
# :web (http: https: fpt:)
|
217
|
+
# :mem - some type of memory structure
|
218
|
+
def default_scheme
|
219
|
+
:unknown
|
220
|
+
end
|
221
|
+
|
222
|
+
# Optionally overridden, this is the case with FileResource
|
223
|
+
def infer_content_type
|
224
|
+
nil
|
225
|
+
end
|
226
|
+
|
227
|
+
def default_content_type
|
228
|
+
:unknown
|
229
|
+
end
|
230
|
+
|
231
|
+
def alive?
|
232
|
+
@status == :alive
|
233
|
+
end
|
234
|
+
|
235
|
+
def content_loaded?
|
236
|
+
@status == :content_loaded
|
237
|
+
end
|
238
|
+
|
239
|
+
def documents_registered?
|
240
|
+
@status == :documents_registered
|
241
|
+
end
|
242
|
+
|
243
|
+
def documents_loaded?
|
244
|
+
@status == :documents_loaded
|
245
|
+
end
|
246
|
+
|
247
|
+
# Setting the URI can be overridden by WebResource and FileResource
|
248
|
+
def uri=(uri)
|
249
|
+
return if uri.nil?
|
250
|
+
|
251
|
+
@uri = URI(uri) if uri.is_a?(String)
|
252
|
+
@uri = uri if uri.is_a?(URI)
|
253
|
+
|
254
|
+
# log.kv 'uri type', uri.class
|
255
|
+
# It might be useful to have a Resource Specific Guard being called to warn if the wrong URI type is inferred from here
|
256
|
+
# supported URI::Class (Generic, File, HTTP, HTTPS)
|
136
257
|
end
|
137
258
|
|
138
259
|
# rubocop:disable Metrics/AbcSize
|
139
|
-
def
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
260
|
+
def attribute_values(prefix = nil)
|
261
|
+
result = {}
|
262
|
+
result["#{prefix}id".to_sym] = object_id
|
263
|
+
result["#{prefix}key".to_sym] = infer_key
|
264
|
+
result["#{prefix}namespace".to_sym] = namespace
|
265
|
+
result["#{prefix}status".to_sym] = status
|
266
|
+
result["#{prefix}source".to_sym] = source_path
|
267
|
+
result["#{prefix}content_type".to_sym] = content_type
|
268
|
+
result["#{prefix}content".to_sym] = content
|
269
|
+
result["#{prefix}document_count".to_sym] = documents.length
|
270
|
+
result["#{prefix}errors".to_sym] = error_hash
|
271
|
+
result["#{prefix}valid".to_sym] = valid?
|
272
|
+
result["#{prefix}scheme".to_sym] = scheme
|
273
|
+
result["#{prefix}host".to_sym] = host
|
274
|
+
result
|
275
|
+
end
|
276
|
+
# rubocop:enable Metrics/AbcSize
|
277
|
+
|
278
|
+
# rubocop:disable Metrics/AbcSize
|
279
|
+
def debug(heading = 'resource')
|
280
|
+
width = 20
|
281
|
+
log.section_heading(heading)
|
282
|
+
log.kv 'area' , area.name , width if area
|
283
|
+
log.kv 'area namespace' , area.namespace , width if area
|
284
|
+
log.kv 'scheme' , scheme , width
|
285
|
+
log.kv 'host' , host , width
|
286
|
+
log.kv 'source_path' , source_path , width
|
287
|
+
log.kv 'content_type' , content_type , width
|
288
|
+
log.kv 'status' , status , width
|
289
|
+
log.kv 'content' , content.nil? ? '' : content[0..100].gsub("\n", '\n') , width
|
290
|
+
log.kv 'documents' , documents.length , width
|
291
|
+
|
292
|
+
yield if block_given?
|
293
|
+
|
294
|
+
log_any_messages
|
295
|
+
|
296
|
+
# log.kv 'infer_key', infer_key , width
|
144
297
|
# log.kv 'project' , project
|
145
|
-
log.kv 'content' , content.nil? ? '' : content[0..100].gsub("\n", '\n') , 15
|
146
|
-
log.kv 'documents', documents.length , 15
|
147
298
|
|
148
299
|
documents.each(&:debug)
|
300
|
+
nil
|
149
301
|
end
|
150
302
|
# rubocop:enable Metrics/AbcSize
|
151
303
|
|
152
304
|
private
|
153
305
|
|
154
|
-
def
|
155
|
-
|
156
|
-
|
157
|
-
|
306
|
+
def value_remove(opts, key)
|
307
|
+
return opts.delete(key) if opts.key?(key)
|
308
|
+
|
309
|
+
nil
|
158
310
|
end
|
159
311
|
|
160
312
|
def load_content_action
|
161
313
|
@status = :content_loading
|
162
|
-
@content = nil
|
163
314
|
load_content
|
164
315
|
@status = :content_loaded
|
165
316
|
end
|
@@ -2,91 +2,114 @@
|
|
2
2
|
|
3
3
|
module KManager
|
4
4
|
module Resources
|
5
|
-
|
6
|
-
|
7
|
-
# A file resource represents context that is loaded via a file.
|
5
|
+
# A file resource represents content that is loaded via a file.
|
8
6
|
#
|
9
7
|
# File resources have the benefit that file watchers can watch them
|
10
|
-
# locally and reload these resources on change.
|
8
|
+
# locally and reload when these resources on change.
|
11
9
|
class FileResource < KManager::Resources::BaseResource
|
12
10
|
include KLog::Logging
|
13
11
|
|
14
|
-
|
12
|
+
KNOWN_EXTENSIONS = {
|
13
|
+
'.rb' => :ruby,
|
14
|
+
'.csv' => :csv,
|
15
|
+
'.json' => :json,
|
16
|
+
'.yaml' => :yaml
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
def initialize(uri, **opts)
|
20
|
+
warn('URI::File type expected for File Resource') unless uri.is_a?(URI::File)
|
21
|
+
super(uri, **opts)
|
22
|
+
log_any_messages unless valid?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Infer key is the file name without the extension stored in dash-case
|
26
|
+
def infer_key
|
27
|
+
file_name = Pathname.new(source_path).basename.sub_ext('').to_s
|
28
|
+
Handlebars::Helpers::StringFormatting::Snake.new.parse(file_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_scheme
|
32
|
+
:file
|
33
|
+
end
|
34
|
+
|
35
|
+
# Currently in base
|
36
|
+
# def register_document
|
37
|
+
# KManager::Resources::ResourceDocumentFactory.create_documents(self)
|
38
|
+
# end
|
39
|
+
|
40
|
+
def attribute_values(prefix = nil)
|
41
|
+
result = super(prefix)
|
42
|
+
result["#{prefix}path".to_sym] = resource_path
|
43
|
+
result["#{prefix}relative_path".to_sym] = resource_relative_path
|
44
|
+
result["#{prefix}exist".to_sym] = resource_valid?
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
def debug
|
49
|
+
super do
|
50
|
+
log.kv 'infer_key' , infer_key , 20
|
51
|
+
log.kv 'file' , source_path , 20
|
52
|
+
log.kv 'resource_path' , resource_path , 20
|
53
|
+
log.kv 'resource_valid?' , resource_valid? , 20
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Source path - aka Full path to file
|
15
58
|
#
|
16
59
|
# example: /Users/davidcruwys/dev/kgems/k_dsl/spec/factories/dsls/common-auth/admin_user.rb
|
17
|
-
|
60
|
+
def source_path
|
61
|
+
uri.path
|
62
|
+
end
|
18
63
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@file = opts[:file]
|
64
|
+
# TODO: Write tests
|
65
|
+
def recreate(resource)
|
66
|
+
raise 'Recreate only works for resources of the same type' unless resource.is_a?(self.class)
|
23
67
|
|
24
|
-
|
68
|
+
# area: resource.area,
|
69
|
+
# content_type: resource.content_type,
|
70
|
+
opts = {
|
71
|
+
area: resource.area,
|
72
|
+
namespace: resource.namespace
|
73
|
+
}
|
74
|
+
|
75
|
+
resource.class.new(resource.uri, **opts)
|
25
76
|
end
|
26
77
|
|
27
|
-
|
28
|
-
|
29
|
-
file = opts[:file]
|
30
|
-
|
31
|
-
extension = ::File.extname(file).downcase
|
32
|
-
|
33
|
-
case extension
|
34
|
-
when '.rb'
|
35
|
-
KManager::Resources::RubyFileResource.new(**opts)
|
36
|
-
when '.csv'
|
37
|
-
KManager::Resources::CsvFileResource.new(**opts)
|
38
|
-
when '.json'
|
39
|
-
KManager::Resources::JsonFileResource.new(**opts)
|
40
|
-
when '.yaml'
|
41
|
-
KManager::Resources::YamlFileResource.new(**opts)
|
42
|
-
else
|
43
|
-
KManager::Resources::UnknownFileResource.new(**opts)
|
44
|
-
end
|
45
|
-
end
|
78
|
+
def resource_path
|
79
|
+
@resource_path ||= absolute_path(source_path)
|
46
80
|
end
|
47
81
|
|
48
|
-
|
49
|
-
|
50
|
-
file_name = Pathname.new(@file).basename.sub_ext('').to_s
|
51
|
-
Handlebars::Helpers::StringFormatting::Dasherize.new.parse(file_name)
|
82
|
+
def resource_relative_path(from_path = Dir.pwd)
|
83
|
+
Pathname.new(resource_path).relative_path_from(from_path).to_s
|
52
84
|
end
|
53
85
|
|
86
|
+
def resource_valid?
|
87
|
+
File.exist?(resource_path)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
54
92
|
def load_content
|
55
|
-
if
|
93
|
+
if resource_valid?
|
56
94
|
begin
|
57
|
-
@content = File.read(
|
95
|
+
@content = File.read(resource_path)
|
58
96
|
rescue StandardError => e
|
59
97
|
log.error e
|
60
98
|
end
|
61
99
|
else
|
62
|
-
|
100
|
+
guard("Source file not found: #{resource_path}")
|
63
101
|
end
|
64
102
|
end
|
65
103
|
|
66
|
-
def
|
67
|
-
|
68
|
-
end
|
104
|
+
def absolute_path(path)
|
105
|
+
pn = Pathname(path)
|
69
106
|
|
70
|
-
|
71
|
-
def debug
|
72
|
-
log.section_heading('resource')
|
73
|
-
log.kv 'source' , source , 15
|
74
|
-
log.kv 'file' , file , 15
|
75
|
-
log.kv 'type' , type , 15
|
76
|
-
log.kv 'infer_key', infer_key , 15
|
77
|
-
log.kv 'status' , status , 15
|
78
|
-
# log.kv 'project' , project
|
79
|
-
log.kv 'content' , content.nil? ? '' : content[0..100].gsub("\n", '\n') , 15
|
80
|
-
log.kv 'documents', documents.length , 15
|
81
|
-
|
82
|
-
documents.each(&:debug)
|
107
|
+
pn.exist? ? pn.realpath.to_s : File.expand_path(path)
|
83
108
|
end
|
84
|
-
# rubocop:enable Metrics/AbcSize
|
85
|
-
|
86
|
-
private
|
87
109
|
|
88
|
-
def
|
89
|
-
|
110
|
+
def infer_content_type
|
111
|
+
extension = ::File.extname(source_path).downcase
|
112
|
+
KNOWN_EXTENSIONS[extension]
|
90
113
|
end
|
91
114
|
end
|
92
115
|
end
|
File without changes
|
data/lib/k_manager/resources/{unknown_file_resource.rb → file_resources/unknown_file_resource.rb}
RENAMED
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module KManager
|
6
|
+
module Resources
|
7
|
+
require 'handlebars/helpers/string_formatting/dasherize'
|
8
|
+
|
9
|
+
# A memory resource represents content that is generated programmatically and just stored in memory.
|
10
|
+
class MemResource < KManager::Resources::BaseResource
|
11
|
+
def initialize(**opts)
|
12
|
+
fake_uri = URI.parse("mem://#{SecureRandom.alphanumeric(4)}")
|
13
|
+
super(fake_uri, **opts)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KManager
|
4
|
+
module Resources
|
5
|
+
# Create documents based on the target resource
|
6
|
+
#
|
7
|
+
# This factory will lock the resource and then create
|
8
|
+
# new documents based on the content of the resource.
|
9
|
+
#
|
10
|
+
# In the case of a ruby resource, this factory will evaluate the ruby
|
11
|
+
# code dynamically and any ruby file with standard document DSL's will
|
12
|
+
# create additional documents using KManager::DocumentFactory
|
13
|
+
class ResourceDocumentFactory
|
14
|
+
# TODO: The original system always created 1 document, so need to consider if 0-more should become 1-more
|
15
|
+
class << self
|
16
|
+
include KLog::Logging
|
17
|
+
# Build 0-more documents and attach them to the resource.
|
18
|
+
#
|
19
|
+
# The resource is stored in the KManager.current_resource context
|
20
|
+
# and wrapped by a Mutex so that any self registering documents can
|
21
|
+
# figure out which resource to register themselves against
|
22
|
+
def create_documents(target_resource)
|
23
|
+
KManager.for_resource(target_resource) do |resource|
|
24
|
+
process_resource(resource)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Create 0-Many documents and attach to the resource
|
31
|
+
#
|
32
|
+
# @param [BaseResource] resource The resource that created and is thus owns the document
|
33
|
+
# @param [Symbol] content_type Type of content, %i[csv json yaml ruby unknown]
|
34
|
+
# @param [String] key is the unique resource key
|
35
|
+
# @param [String] content Resource content as a raw string, examples could be CSV, JSON, YAML, RUBY or some other text content
|
36
|
+
def process_resource(resource)
|
37
|
+
case resource.content_type
|
38
|
+
when :csv
|
39
|
+
resource.new_document(process_csv(resource.content))
|
40
|
+
when :json
|
41
|
+
resource.new_document(process_json(resource.content))
|
42
|
+
when :yaml
|
43
|
+
resource.new_document(process_yaml(resource.content))
|
44
|
+
when :ruby
|
45
|
+
process_ruby(resource)
|
46
|
+
:ruby
|
47
|
+
else
|
48
|
+
:unknown
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def process_csv(content)
|
53
|
+
rows = []
|
54
|
+
|
55
|
+
CSV.parse(content, headers: true, header_converters: :symbol) do |row|
|
56
|
+
rows << row.to_h
|
57
|
+
end
|
58
|
+
rows
|
59
|
+
rescue StandardError => e
|
60
|
+
log.exception(e, style: :message)
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
|
64
|
+
def process_json(content)
|
65
|
+
JSON.parse(content)
|
66
|
+
rescue StandardError => e
|
67
|
+
log.exception(e, style: :message)
|
68
|
+
{}
|
69
|
+
end
|
70
|
+
|
71
|
+
def process_yaml(content)
|
72
|
+
YAML.safe_load(content)
|
73
|
+
rescue StandardError => e
|
74
|
+
log.exception(e, style: :message)
|
75
|
+
{}
|
76
|
+
end
|
77
|
+
|
78
|
+
# rubocop:disable Lint/RescueException
|
79
|
+
def process_ruby(resource)
|
80
|
+
# puts content
|
81
|
+
# KManager::Manager.current_resource
|
82
|
+
# KDsl.target_resource = self
|
83
|
+
|
84
|
+
# log.error "#{resource.activated?} - #{resource.resource_path}"
|
85
|
+
|
86
|
+
Object.class_eval resource.content, resource.resource_path
|
87
|
+
|
88
|
+
# # Only DSL's will add new resource_documents
|
89
|
+
# if documents.length > 0
|
90
|
+
# resource.resource_type = KDsl::Resources::Resource::TYPE_RUBY_DSL
|
91
|
+
# end
|
92
|
+
rescue Interrupt, SystemExit
|
93
|
+
raise
|
94
|
+
rescue Exception => e
|
95
|
+
# Report the error but still add the document so that you can see
|
96
|
+
# it in the ResourceDocument list, it will be marked as Error
|
97
|
+
# resource.error = ex
|
98
|
+
resource.guard(e.message)
|
99
|
+
resource.debug
|
100
|
+
log.exception(e, style: :short)
|
101
|
+
|
102
|
+
# L.exception resource.error
|
103
|
+
|
104
|
+
# KDsl.target_resource = nil
|
105
|
+
|
106
|
+
# # A regular ruby file would not add resource_documents
|
107
|
+
# # so create one manually
|
108
|
+
# add_document(new_document) if documents.length === 0
|
109
|
+
end
|
110
|
+
# rubocop:enable Lint/RescueException
|
111
|
+
|
112
|
+
# # TEST REQUIRED
|
113
|
+
# def add_document(document)
|
114
|
+
# # project.register_dsl(document)
|
115
|
+
# project.add_resource_document(self, document)
|
116
|
+
# document.resource = self
|
117
|
+
# documents << document
|
118
|
+
# document
|
119
|
+
# end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KManager
|
4
|
+
module Resources
|
5
|
+
class ResourceFactory
|
6
|
+
# TODO: Write tests
|
7
|
+
|
8
|
+
# Create a resource based on a resource URI.
|
9
|
+
#
|
10
|
+
# Resources may be of type File or Web
|
11
|
+
#
|
12
|
+
# The resource content_type should be passed in when it cannot be inferred (e.g. WebResource)
|
13
|
+
# for a FileResource this option is optional and will be inferred from the file extension.
|
14
|
+
def instance(resource_uri, **opts)
|
15
|
+
scheme = resource_uri.scheme.to_sym
|
16
|
+
|
17
|
+
case scheme
|
18
|
+
when :file
|
19
|
+
FileResource.new(resource_uri, **opts)
|
20
|
+
when :http, :https
|
21
|
+
WebResource.new(resource_uri, **opts)
|
22
|
+
else
|
23
|
+
raise 'Unknown schema'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|