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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/Gemfile +23 -0
  4. data/Rakefile +2 -0
  5. data/docs/flow.drawio +16 -0
  6. data/exe/k_manager +19 -0
  7. data/hooks/update-version +1 -1
  8. data/k_manager.gemspec +9 -0
  9. data/lib/k_manager/area.rb +49 -0
  10. data/lib/k_manager/cli/base_command.rb +23 -0
  11. data/lib/k_manager/cli/commands.rb +25 -0
  12. data/lib/k_manager/cli/info.rb +81 -0
  13. data/lib/k_manager/cli/new.rb +130 -0
  14. data/lib/k_manager/cli/version.rb +15 -0
  15. data/lib/k_manager/cli/watch.rb +65 -0
  16. data/lib/k_manager/document_factory.rb +81 -0
  17. data/lib/k_manager/manager.rb +158 -0
  18. data/lib/k_manager/overview/dashboard.rb +197 -0
  19. data/lib/k_manager/overview/dump_json.rb +35 -0
  20. data/lib/k_manager/overview/models.rb +76 -0
  21. data/lib/k_manager/overview/queries.rb +53 -0
  22. data/lib/k_manager/resources/base_resource.rb +203 -52
  23. data/lib/k_manager/resources/file_resource.rb +81 -58
  24. data/lib/k_manager/resources/{ruby_file_resource.rb → file_resources/ruby_file_resource.rb} +0 -0
  25. data/lib/k_manager/resources/{unknown_file_resource.rb → file_resources/unknown_file_resource.rb} +0 -0
  26. data/lib/k_manager/resources/mem_resource.rb +17 -0
  27. data/lib/k_manager/resources/resource_document_factory.rb +123 -0
  28. data/lib/k_manager/resources/resource_factory.rb +28 -0
  29. data/lib/k_manager/resources/resource_manager.rb +201 -0
  30. data/lib/k_manager/resources/resource_set.rb +90 -0
  31. data/lib/k_manager/resources/web_resource.rb +113 -0
  32. data/lib/k_manager/version.rb +1 -1
  33. data/lib/k_manager/watcher.rb +113 -0
  34. data/lib/k_manager/{x_project.rb → x_resource_documents/x_project.rb} +0 -0
  35. data/lib/k_manager/{x_project_manager.rb → x_resource_documents/x_project_manager.rb} +0 -0
  36. data/lib/k_manager/{x_register.rb → x_resource_documents/x_register.rb} +0 -0
  37. data/lib/k_manager.rb +111 -24
  38. data/tasks/watch.rake +18 -0
  39. metadata +118 -25
  40. data/Assessment1.md +0 -127
  41. data/Assessment2.md +0 -88
  42. data/lib/k_manager/configuration/project_config.rb +0 -14
  43. data/lib/k_manager/create_document.rb +0 -31
  44. data/lib/k_manager/documents/basic_document.rb +0 -21
  45. data/lib/k_manager/documents/builder_document.rb +0 -18
  46. data/lib/k_manager/documents/document_taggable.rb +0 -94
  47. data/lib/k_manager/documents/model_document.rb +0 -19
  48. data/lib/k_manager/project.rb +0 -50
  49. data/lib/k_manager/resources/csv_file_resource.rb +0 -27
  50. data/lib/k_manager/resources/factories/document_factory.rb +0 -52
  51. data/lib/k_manager/resources/json_file_resource.rb +0 -22
  52. data/lib/k_manager/resources/yaml_file_resource.rb +0 -21
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ # KManager is designed to work with one or more areas of concern
5
+ #
6
+ # TODO: Write Tests
7
+ class Manager
8
+ attr_accessor :active_uri
9
+
10
+ # NOTE: rename current_resource to active_resource, focused_resource?
11
+ attr_reader :current_resource
12
+
13
+ def resource_mutex
14
+ @resource_mutex ||= Mutex.new
15
+ end
16
+
17
+ def for_resource(resource = nil)
18
+ resource_mutex.synchronize do
19
+ @current_resource = resource
20
+ yield(current_resource)
21
+ @current_resource = nil
22
+ end
23
+ end
24
+
25
+ def for_current_resource
26
+ raise KManager::Error, 'Attempting to yield current_resource, when a different thread has the lock?' unless resource_mutex.owned?
27
+
28
+ yield(@current_resource)
29
+ end
30
+
31
+ # Usage
32
+ #
33
+ # KManager.opts.sleep = 10
34
+ # KManager.opts.reboot_on_kill = 0
35
+ # KManager.opts.exception_style = :short
36
+ # KManager.opts.show.time_taken = true
37
+ # KManager.opts.show.finished = true
38
+ # KManager.opts.show.finished_message = 'FINISHED :)'
39
+
40
+ Options = Struct.new(
41
+ :app_name,
42
+ :exception_style,
43
+ :reboot_on_kill,
44
+ :reboot_sleep,
45
+ :sleep,
46
+ :show
47
+ )
48
+
49
+ Show = Struct.new(
50
+ :time_taken,
51
+ :finished,
52
+ :finished_message
53
+ )
54
+
55
+ # @param [Integer] sleep Seconds to sleep after running, 0 = no sleep
56
+ # @param [Symbol] exception_style Format for exception messages caught by watcher.
57
+ # :message - message only
58
+ # :short - message and short backtrace
59
+ # :long - message and long backtrace
60
+ def opts
61
+ @opts ||= Options.new('', :message, false, 1, 0, Show.new(true, true, 'FINISHED :)'))
62
+ end
63
+
64
+ def areas
65
+ @areas ||= []
66
+ end
67
+
68
+ def add_area(name, namespace: nil)
69
+ area = find_area(name)
70
+
71
+ return area if area
72
+
73
+ area = KManager::Area.new(manager: self, name: name, namespace: namespace)
74
+ areas << area
75
+ area
76
+ end
77
+
78
+ def find_document(tag, area: nil)
79
+ area = resolve_area(area)
80
+
81
+ log.error 'Could not resolve area' if area.nil?
82
+
83
+ log.line
84
+ log.error(tag)
85
+ log.line
86
+
87
+ documents = area.resources.flat_map(&:documents)
88
+ documents.find { |d| d.tag == tag }
89
+ end
90
+
91
+ def fire_actions(*actions)
92
+ areas.each do |area|
93
+ # delegate
94
+ area.resource_manager.fire_actions(*actions)
95
+ end
96
+ end
97
+
98
+ def find_area(name)
99
+ areas.find { |a| a.name == name }
100
+ end
101
+
102
+ def resolve_area(area)
103
+ if area.nil?
104
+ return KManager.current_resource.area if KManager.current_resource
105
+
106
+ return KManager.areas.first
107
+ end
108
+
109
+ return area if area.is_a?(Area)
110
+
111
+ find_area(name)
112
+ end
113
+
114
+ # Return a list of resources for a URI.
115
+ #
116
+ # Generally only one resource is returned, unless the URI exists in more than one area
117
+ def resources_by_uri(uri)
118
+ areas.map { |area| area.resources_by_uri(uri) }.compact
119
+ end
120
+
121
+ def resource_changed(uri, state)
122
+ @active_uri = uri
123
+ areas.each do |area|
124
+ area.resource_changed(uri, state)
125
+ end
126
+ @active_uri = nil
127
+ end
128
+
129
+ def reboot
130
+ puts 'Fire reboot'
131
+ KManager.opts.reboot_on_kill = 1
132
+ raise SystemExit
133
+ end
134
+
135
+ def debug(*sections)
136
+ log.structure(KUtil.data.to_hash(opts))
137
+
138
+ areas.each do |area|
139
+ area.debug(*sections)
140
+ end
141
+ end
142
+
143
+ # def cons
144
+
145
+ # # May replace config with default channel name
146
+ # # Channels represent configurations that are independent of project or builder,
147
+ # # but a project may want to have a default channel that it supplies
148
+ # def initialize(name, config = nil, **opts)
149
+ # raise KType::Error, 'Provide a project name' unless name.is_a?(String) || name.is_a?(Symbol)
150
+
151
+ # @name = name
152
+ # @config = config || KManager::Configuration::ProjectConfig.new
153
+ # @resources = []
154
+
155
+ # initialize_opts(opts)
156
+ # end
157
+ end
158
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Overview
5
+ # Generate dashboard information on the console
6
+ #
7
+ # TODO: ConsoleDashboard and HtmlConsole
8
+ class Dashboard
9
+ include KLog::Logging
10
+
11
+ attr_reader :queries
12
+
13
+ def initialize(manager)
14
+ @queries = KManager::Overview::Queries.new(manager)
15
+ end
16
+
17
+ def areas
18
+ data = queries.areas.map { |hash| KManager::Overview::Area.new(hash) }
19
+ graph = {
20
+ areas: {
21
+ columns: [
22
+ :name,
23
+ :namespace,
24
+ { resource_count: { display_method: ->(row) { blank_zero(row.resource_count) } } },
25
+ { document_count: { display_method: ->(row) { blank_zero(row.document_count) } } }
26
+
27
+ ]
28
+ }
29
+ }
30
+ display(:areas, 'Areas', graph, data)
31
+ end
32
+
33
+ # rubocop:disable Metrics/AbcSize
34
+ def resources
35
+ # sort and remove repeating area
36
+ data = grouped_resources(queries.resources).map { |hash| KManager::Overview::Resource.new(hash) }
37
+ graph = {
38
+ resources: {
39
+ columns: [
40
+ { area: { display_method: ->(row) { row.area_name } } },
41
+ { area_ns: { display_method: ->(row) { row.area_namespace } } },
42
+ { resource_docs: { display_method: ->(row) { resource_document_count(row) } } },
43
+ { resource_id: { display_method: ->(row) { blank_zero(row.id) } } },
44
+ { key: { display_method: ->(row) { row.key } } },
45
+ { namespace: { display_method: ->(row) { row.namespace } } },
46
+ { status: { display_method: ->(row) { row.status } } },
47
+ { content_type: { display_method: ->(row) { row.content_type } } },
48
+ { content: { display_method: ->(row) { format_content(row.content, row.content_type) }, width: 50 } },
49
+ { document_count: { display_method: ->(row) { blank_zero(row.document_count) } } },
50
+ { valid: { display_method: ->(row) { row.valid } } },
51
+ { error_count: { display_method: ->(row) { blank_zero(row.errors.length) } } },
52
+ { scheme: { display_method: ->(row) { row.scheme } } },
53
+ { root: { display_method: ->(row) { row.scheme == :file ? '' : row.host } } },
54
+ { relative_path: { display_method: ->(row) { right(50, row.relative_path) }, width: 50 } },
55
+ { exist: { display_method: ->(row) { row.exist } } } # ,
56
+ # { resource_path: { display_method: ->(row) { row.path }, width: 100 } }
57
+ ]
58
+ }
59
+ }
60
+
61
+ display(:resources, 'Resource List', graph, data)
62
+ end
63
+
64
+ def documents
65
+ data = grouped_documents(queries.documents).map { |hash| KManager::Overview::Document.new(hash) }
66
+
67
+ graph = {
68
+ resources: {
69
+ columns: [
70
+ { area: { display_method: ->(row) { row.area_name } } },
71
+ { area_ns: { display_method: ->(row) { row.area_namespace } } },
72
+ { resource_docs: { display_method: ->(row) { resource_document_count(row) } } },
73
+ { resource_id: { display_method: ->(row) { blank_zero(row.resource_id) } } },
74
+ # { key: { display_method: -> (row) { row.resource_key } } },
75
+ # { namespace: { display_method: -> (row) { row.resource_namespace } } },
76
+ # { status: { display_method: -> (row) { row.resource_status } } },
77
+ # { content_type: { display_method: -> (row) { row.resource_content_type } } },
78
+ # { content: { display_method: -> (row) { row.resource_content } } },
79
+ # { document_count: { display_method: -> (row) { blank_zero(row.resource_document_count) } } },
80
+ # { valid: { display_method: -> (row) { row.resource_valid } } },
81
+ # { error_count: { display_method: -> (row) { blank_zero(row.resource_errors.length) } } },
82
+ # { scheme: { display_method: -> (row) { row.resource_scheme } } },
83
+ # # { path: { display_method: -> (row) { row.resource_path } } },
84
+ # { exist: { display_method: -> (row) { row.resource_exist } } },
85
+ { document_id: { display_method: ->(row) { blank_zero(row.document_id) } } },
86
+ { data: { display_method: ->(row) { row.document_data } } },
87
+ { error_count: { display_method: ->(row) { blank_zero(row.document_errors.length) } } },
88
+ { key: { display_method: ->(row) { row.document_key } } },
89
+ { namespace: { display_method: ->(row) { row.document_namespace } } },
90
+ { tag: { display_method: ->(row) { row.document_tag } } },
91
+ { type: { display_method: ->(row) { row.document_type } } },
92
+ { relative_path: { display_method: ->(row) { right(50, resource_path_location(row.resource_relative_path, row.document_location)) }, width: 50 } }
93
+ ]
94
+ }
95
+ }
96
+
97
+ display(:resources, 'Document List', graph, data)
98
+ end
99
+ # rubocop:enable Metrics/AbcSize
100
+
101
+ private
102
+
103
+ def resource_path_location(path, location)
104
+ return path unless location
105
+
106
+ "#{path}:#{location}"
107
+ end
108
+
109
+ def display(section, title, graph, data)
110
+ data = {
111
+ section => data
112
+ }
113
+ opts = {
114
+ title: title,
115
+ title_type: :heading,
116
+ show_array_count: false,
117
+ graph: graph
118
+ }
119
+ log.structure(data, **opts)
120
+ end
121
+
122
+ def format_content(content, type)
123
+ formatted = content
124
+ case type
125
+ when :ruby
126
+ formatted = formatted&.sub(/\A# frozen_string_literal: true/, '')&.strip
127
+ end
128
+ formatted
129
+ end
130
+
131
+ def blank_zero(value)
132
+ return nil if value.nil? || (value.is_a?(Integer) && value.zero?)
133
+
134
+ value
135
+ end
136
+
137
+ def lpad(size, value)
138
+ value.to_s.rjust(size)
139
+ end
140
+
141
+ def right(size, value)
142
+ value.chars.last(size).join
143
+ end
144
+
145
+ def resource_document_count(row)
146
+ return nil if row.area_resource_count.nil? && row.area_document_count.nil?
147
+
148
+ resource = lpad(2, blank_zero(row.area_resource_count))
149
+ document = lpad(2, blank_zero(row.area_document_count))
150
+ [resource, document].join(' / ')
151
+ end
152
+
153
+ # rubocop:disable Metrics/AbcSize
154
+ def grouped_resources(resources)
155
+ return resources if resources.length < 2
156
+
157
+ grouped = resources.group_by { |resource| resource[:area_name] }
158
+ grouped.flat_map do |group|
159
+ group[1].map.with_index do |resource, index|
160
+ new_resource = resource.clone
161
+ if index.positive?
162
+ new_resource[:area_name] = nil
163
+ new_resource[:area_namespace] = nil
164
+ new_resource[:area_resource_count] = nil
165
+ new_resource[:area_document_count] = nil
166
+ end
167
+ new_resource
168
+ end
169
+ end
170
+ end
171
+
172
+ def grouped_documents(documents)
173
+ return documents if documents.length < 2
174
+
175
+ grouped = documents.group_by { |document| document[:area_name] }
176
+ grouped.flat_map do |group|
177
+ last_resource_id = 0
178
+ group[1].map.with_index do |document, index|
179
+ new_document = document.clone
180
+ if index.positive?
181
+ new_document[:area_name] = nil
182
+ new_document[:area_namespace] = nil
183
+ new_document[:area_resource_count] = nil
184
+ new_document[:area_document_count] = nil
185
+
186
+ new_document[:resource_id] = nil if last_resource_id == group[1][index][:resource_id]
187
+
188
+ end
189
+ last_resource_id = document[:resource_id]
190
+ new_document
191
+ end
192
+ end
193
+ end
194
+ # rubocop:enable Metrics/AbcSize
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Overview
5
+ class DumpJson
6
+ attr_reader :path
7
+ attr_reader :queries
8
+
9
+ def initialize(path, manager)
10
+ @path = path
11
+ @queries = KManager::Overview::Queries.new(manager)
12
+ end
13
+
14
+ def areas(file_name)
15
+ dump(file_name, queries.areas)
16
+ end
17
+
18
+ def resources(file_name)
19
+ dump(file_name, queries.resources)
20
+ end
21
+
22
+ def documents(file_name)
23
+ dump(file_name, queries.documents)
24
+ end
25
+
26
+ private
27
+
28
+ def dump(file_name, data)
29
+ file = File.join(path, file_name)
30
+ json = JSON.pretty_generate(data)
31
+ File.write(file, json)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # KDomain::Schemas::Domain::Column
4
+ # KDomain::Schemas::Domain::Model
5
+
6
+ module KManager
7
+ module Overview
8
+ module Types
9
+ include Dry.Types()
10
+ end
11
+
12
+ class Error < Dry::Struct
13
+ end
14
+
15
+ class Area < Dry::Struct
16
+ attribute :name , Types::Strict::String | Types::Strict::Symbol
17
+ attribute :namespace , Types::Strict::String.optional.default(nil) | Types::Strict::Symbol.optional.default(nil)
18
+ attribute :resource_count , Types::Strict::Integer
19
+ attribute :document_count , Types::Strict::Integer
20
+ end
21
+
22
+ class Resource < Dry::Struct
23
+ attribute :area_name , Types::Strict::String.optional.default(nil) | Types::Strict::Symbol.optional.default(nil)
24
+ attribute :area_namespace , Types::Strict::String.optional.default(nil) | Types::Strict::Symbol.optional.default(nil)
25
+ attribute :area_resource_count , Types::Strict::Integer.optional.default(nil)
26
+ attribute :area_document_count , Types::Strict::Integer.optional.default(nil)
27
+ attribute :id , Types::Strict::Integer
28
+ attribute :key , Types::Strict::String
29
+ attribute :namespace , Types::Strict::String | Types::Strict::Array.of(Types::Strict::String).optional.default(nil)
30
+ attribute :status , Types::Strict::String | Types::Strict::Symbol
31
+ attribute :source , Types::Strict::String
32
+ attribute :content_type , Types::Strict::String | Types::Strict::Symbol
33
+ attribute :content , Types::Strict::String.optional.default(nil)
34
+ attribute :document_count , Types::Strict::Integer
35
+ attribute :errors , Types::Strict::Array.of(KManager::Overview::Error).optional.default(nil)
36
+ attribute :valid? , Types::Strict::Bool
37
+ attribute :scheme , Types::Strict::String | Types::Strict::Symbol
38
+ attribute :host , Types::Strict::String
39
+ attribute :path , Types::Strict::String
40
+ attribute :relative_path , Types::Strict::String.optional.default(nil)
41
+ attribute :exist? , Types::Strict::Bool
42
+ end
43
+
44
+ class Document < Dry::Struct
45
+ attribute :area_name , Types::Strict::String.optional.default(nil) | Types::Strict::Symbol.optional.default(nil)
46
+ attribute :area_namespace , Types::Strict::String.optional.default(nil) | Types::Strict::Symbol.optional.default(nil)
47
+ attribute :area_resource_count , Types::Strict::Integer.optional.default(nil)
48
+ attribute :area_document_count , Types::Strict::Integer.optional.default(nil)
49
+ attribute :resource_id , Types::Strict::Integer.optional.default(nil)
50
+ attribute :resource_key , Types::Strict::String
51
+ attribute :resource_namespace , Types::Strict::Array.of(Types::Strict::String).optional.default(nil)
52
+ attribute :resource_status , Types::Strict::String | Types::Strict::Symbol
53
+ attribute :resource_source , Types::Strict::String
54
+ attribute :resource_content_type , Types::Strict::String | Types::Strict::Symbol
55
+ attribute :resource_content , Types::Strict::String.optional.default(nil)
56
+ attribute :resource_document_count , Types::Strict::Integer
57
+ attribute :resource_errors , Types::Strict::Array.of(KManager::Overview::Error).optional.default(nil)
58
+ attribute :resource_valid? , Types::Strict::Bool
59
+ attribute :resource_scheme , Types::Strict::String | Types::Strict::Symbol
60
+ attribute :resource_host , Types::Strict::String
61
+ attribute :resource_path , Types::Strict::String
62
+ attribute :resource_relative_path , Types::Strict::String.optional.default(nil)
63
+ attribute :resource_exist? , Types::Strict::Bool
64
+ attribute :document_id , Types::Strict::Integer
65
+ attribute :document_data , Types::Strict::Any.optional.default # Hash.optional.default(nil) | Types::Strict::Array.of(Types::Strict::Hash).optional.default(nil)
66
+ attribute :document_key , Types::Strict::String | Types::Strict::Symbol
67
+ attribute :document_namespace , Types::Strict::String | Types::Strict::Array.of(Types::Strict::String).optional.default(nil)
68
+ attribute :document_tag , Types::Strict::String | Types::Strict::Symbol
69
+ attribute :document_type , Types::Strict::String | Types::Strict::Symbol
70
+ # TODO: Write code to populate this with the resource line number
71
+ attribute :document_location , Types::Strict::Integer.optional.default(nil)
72
+ attribute :document_errors , Types::Strict::Array.of(KManager::Overview::Error).optional.default(nil)
73
+ attribute :document_valid? , Types::Strict::Bool
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Overview
5
+ class Queries
6
+ attr_reader :manager
7
+
8
+ def initialize(manager)
9
+ @manager = manager
10
+ end
11
+
12
+ def areas
13
+ manager.areas.map(&:attribute_values)
14
+ end
15
+
16
+ def resources
17
+ manager.areas.flat_map do |area|
18
+ # TODO: Some of these properties are only available on FileResource
19
+ # This will need to be refactored when implementing Mem and Web Resource
20
+ area.resource_manager.resource_set.resources.map do |resource|
21
+ {
22
+ **area.attribute_values('area_'),
23
+ **resource.attribute_values('')
24
+ }
25
+ end
26
+ end
27
+ end
28
+
29
+ # rubocop:disable Metrics/AbcSize
30
+ def documents
31
+ manager.areas.flat_map do |area|
32
+ area.resource_manager.resource_set.resources.flat_map do |resource|
33
+ resource.documents.map do |document|
34
+ {
35
+ **area.attribute_values('area_'),
36
+ **resource.attribute_values('resource_'),
37
+ document_id: document.object_id,
38
+ document_data: document.data,
39
+ document_key: document.key,
40
+ document_namespace: document.namespace,
41
+ document_tag: document.tag,
42
+ document_type: document.type,
43
+ document_errors: document.error_hash,
44
+ document_valid: document.valid?
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ # rubocop:enable Metrics/AbcSize
51
+ end
52
+ end
53
+ end