k_manager 0.0.13 → 0.0.28

Sign up to get free protection for your applications and to get access to all the features.
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