cosmos 5.0.2 → 5.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/cosmos +183 -42
- data/data/config/microservice.yaml +47 -35
- data/data/config/plugins.yaml +10 -147
- data/data/config/target.yaml +70 -0
- data/data/config/tool.yaml +37 -31
- data/ext/cosmos/ext/cosmos_io/cosmos_io.c +14 -14
- data/ext/cosmos/ext/packet/packet.c +3 -3
- data/ext/cosmos/ext/structure/structure.c +31 -31
- data/lib/cosmos/api/api.rb +1 -25
- data/lib/cosmos/api/cmd_api.rb +17 -6
- data/lib/cosmos/api/config_api.rb +10 -4
- data/lib/cosmos/api/limits_api.rb +1 -1
- data/lib/cosmos/api/settings_api.rb +19 -7
- data/lib/cosmos/api/target_api.rb +2 -2
- data/lib/cosmos/api/tlm_api.rb +65 -41
- data/lib/cosmos/config/config_parser.rb +19 -22
- data/lib/cosmos/config/meta_config_parser.rb +1 -1
- data/lib/cosmos/conversions/generic_conversion.rb +2 -2
- data/lib/cosmos/conversions/polynomial_conversion.rb +5 -8
- data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +26 -9
- data/lib/cosmos/io/json_drb.rb +5 -1
- data/lib/cosmos/logs/log_writer.rb +78 -29
- data/lib/cosmos/microservices/cleanup_microservice.rb +28 -29
- data/lib/cosmos/microservices/decom_microservice.rb +1 -1
- data/lib/cosmos/microservices/interface_microservice.rb +0 -16
- data/lib/cosmos/microservices/microservice.rb +3 -3
- data/lib/cosmos/microservices/reducer_microservice.rb +12 -10
- data/lib/cosmos/models/cvt_model.rb +6 -6
- data/lib/cosmos/models/gem_model.rb +9 -3
- data/lib/cosmos/models/info_model.rb +1 -1
- data/lib/cosmos/models/interface_model.rb +16 -7
- data/lib/cosmos/models/interface_status_model.rb +1 -1
- data/lib/cosmos/models/metadata_model.rb +69 -219
- data/lib/cosmos/models/metric_model.rb +2 -2
- data/lib/cosmos/models/microservice_model.rb +7 -4
- data/lib/cosmos/models/microservice_status_model.rb +1 -1
- data/lib/cosmos/models/model.rb +23 -16
- data/lib/cosmos/models/note_model.rb +122 -0
- data/lib/cosmos/models/ping_model.rb +2 -1
- data/lib/cosmos/models/plugin_model.rb +108 -48
- data/lib/cosmos/models/process_status_model.rb +1 -1
- data/lib/cosmos/models/scope_model.rb +10 -25
- data/lib/cosmos/models/settings_model.rb +55 -0
- data/lib/cosmos/models/sorted_model.rb +167 -0
- data/lib/cosmos/models/target_model.rb +143 -27
- data/lib/cosmos/models/tool_config_model.rb +38 -0
- data/lib/cosmos/models/tool_model.rb +9 -9
- data/lib/cosmos/models/widget_model.rb +11 -11
- data/lib/cosmos/operators/microservice_operator.rb +2 -1
- data/lib/cosmos/packets/packet.rb +24 -1
- data/lib/cosmos/packets/packet_config.rb +2 -2
- data/lib/cosmos/packets/packet_item.rb +57 -0
- data/lib/cosmos/packets/packet_item_limits.rb +14 -2
- data/lib/cosmos/packets/parsers/packet_item_parser.rb +1 -1
- data/lib/cosmos/packets/parsers/packet_parser.rb +1 -1
- data/lib/cosmos/packets/parsers/xtce_parser.rb +1 -1
- data/lib/cosmos/packets/structure.rb +30 -33
- data/lib/cosmos/packets/structure_item.rb +10 -1
- data/lib/cosmos/script/api_shared.rb +30 -25
- data/lib/cosmos/script/calendar.rb +37 -15
- data/lib/cosmos/script/commands.rb +5 -7
- data/lib/cosmos/script/script.rb +19 -39
- data/lib/cosmos/script/storage.rb +92 -105
- data/lib/cosmos/system/system.rb +2 -1
- data/lib/cosmos/tools/table_manager/table_config.rb +16 -1
- data/lib/cosmos/tools/table_manager/table_item.rb +1 -1
- data/lib/cosmos/tools/table_manager/table_manager_core.rb +213 -309
- data/lib/cosmos/top_level.rb +5 -1
- data/lib/cosmos/topics/autonomic_topic.rb +2 -2
- data/lib/cosmos/topics/calendar_topic.rb +1 -1
- data/lib/cosmos/topics/command_decom_topic.rb +35 -1
- data/lib/cosmos/topics/command_topic.rb +6 -4
- data/lib/cosmos/topics/config_topic.rb +68 -0
- data/lib/cosmos/topics/interface_topic.rb +8 -8
- data/lib/cosmos/topics/limits_event_topic.rb +5 -3
- data/lib/cosmos/topics/notifications_topic.rb +1 -1
- data/lib/cosmos/topics/router_topic.rb +9 -9
- data/lib/cosmos/topics/telemetry_decom_topic.rb +5 -1
- data/lib/cosmos/topics/telemetry_topic.rb +1 -1
- data/lib/cosmos/topics/timeline_topic.rb +1 -1
- data/lib/cosmos/topics/topic.rb +23 -8
- data/lib/cosmos/utilities/logger.rb +4 -3
- data/lib/cosmos/utilities/metric.rb +32 -26
- data/lib/cosmos/utilities/s3.rb +61 -0
- data/lib/cosmos/utilities/s3_file_cache.rb +12 -6
- data/lib/cosmos/utilities/store.rb +1 -0
- data/lib/cosmos/utilities/store_autoload.rb +25 -134
- data/lib/cosmos/version.rb +5 -4
- data/templates/plugin-template/plugin.gemspec +0 -2
- metadata +12 -10
- data/bin/xtce_converter +0 -92
- data/lib/cosmos/models/narrative_model.rb +0 -280
data/lib/cosmos/models/model.rb
CHANGED
@@ -27,12 +27,16 @@ module Cosmos
|
|
27
27
|
attr_accessor :plugin
|
28
28
|
attr_accessor :scope
|
29
29
|
|
30
|
+
def self.store
|
31
|
+
Store
|
32
|
+
end
|
33
|
+
|
30
34
|
# NOTE: The following three methods must be reimplemented by Model subclasses
|
31
35
|
# without primary_key to support other class methods.
|
32
36
|
|
33
37
|
# @return [Hash|nil] Hash of this model or nil if name not found under primary_key
|
34
38
|
def self.get(primary_key, name:)
|
35
|
-
json =
|
39
|
+
json = store.hget(primary_key, name)
|
36
40
|
if json
|
37
41
|
return JSON.parse(json)
|
38
42
|
else
|
@@ -42,12 +46,12 @@ module Cosmos
|
|
42
46
|
|
43
47
|
# @return [Array<String>] All the names stored under the primary key
|
44
48
|
def self.names(primary_key)
|
45
|
-
|
49
|
+
store.hkeys(primary_key).sort
|
46
50
|
end
|
47
51
|
|
48
52
|
# @return [Array<Hash>] All the models (as Hash objects) stored under the primary key
|
49
53
|
def self.all(primary_key)
|
50
|
-
hash =
|
54
|
+
hash = store.hgetall(primary_key)
|
51
55
|
hash.each do |key, value|
|
52
56
|
hash[key] = JSON.parse(value)
|
53
57
|
end
|
@@ -117,16 +121,6 @@ module Cosmos
|
|
117
121
|
raise "must be implemented by subclass"
|
118
122
|
end
|
119
123
|
|
120
|
-
# TODO: Not used
|
121
|
-
# def self.from_config(primary_key, filename)
|
122
|
-
# model = nil
|
123
|
-
# parser = ConfigParser.new
|
124
|
-
# parser.parse_file(filename) do |keyword, parameters|
|
125
|
-
# model = self.handle_config(primary_key, parser, model, keyword, parameters)
|
126
|
-
# end
|
127
|
-
# model
|
128
|
-
# end
|
129
|
-
|
130
124
|
# Store the primary key and keyword arguments
|
131
125
|
def initialize(primary_key, **kw_args)
|
132
126
|
@primary_key = primary_key
|
@@ -134,13 +128,14 @@ module Cosmos
|
|
134
128
|
@updated_at = kw_args[:updated_at]
|
135
129
|
@plugin = kw_args[:plugin]
|
136
130
|
@scope = kw_args[:scope]
|
131
|
+
@destroyed = false
|
137
132
|
end
|
138
133
|
|
139
134
|
# Update the Redis hash at primary_key and set the field "name"
|
140
135
|
# to the JSON generated via calling as_json
|
141
136
|
def create(update: false, force: false)
|
142
137
|
unless force
|
143
|
-
existing =
|
138
|
+
existing = self.class.store.hget(@primary_key, @name)
|
144
139
|
if existing
|
145
140
|
raise "#{@primary_key}:#{@name} already exists at create" unless update
|
146
141
|
else
|
@@ -148,7 +143,7 @@ module Cosmos
|
|
148
143
|
end
|
149
144
|
end
|
150
145
|
@updated_at = Time.now.to_nsec_from_epoch
|
151
|
-
|
146
|
+
self.class.store.hset(@primary_key, @name, JSON.generate(self.as_json))
|
152
147
|
end
|
153
148
|
|
154
149
|
# Alias for create(update: true)
|
@@ -169,8 +164,14 @@ module Cosmos
|
|
169
164
|
|
170
165
|
# Delete the model from the Store
|
171
166
|
def destroy
|
167
|
+
@destroyed = true
|
172
168
|
undeploy()
|
173
|
-
|
169
|
+
self.class.store.hdel(@primary_key, @name)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Indicate if destroy has been called
|
173
|
+
def destroyed?
|
174
|
+
@destroyed
|
174
175
|
end
|
175
176
|
|
176
177
|
# @return [Hash] JSON encoding of this model
|
@@ -186,4 +187,10 @@ module Cosmos
|
|
186
187
|
""
|
187
188
|
end
|
188
189
|
end
|
190
|
+
|
191
|
+
class EphemeralModel < Model
|
192
|
+
def self.store
|
193
|
+
EphemeralStore
|
194
|
+
end
|
195
|
+
end
|
189
196
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# This program may also be used under the terms of a commercial or
|
17
|
+
# enterprise edition license of COSMOS if purchased from the
|
18
|
+
# copyright holder
|
19
|
+
|
20
|
+
# https://www.rubydoc.info/gems/redis/Redis/Commands/SortedSets
|
21
|
+
|
22
|
+
require 'cosmos/models/sorted_model'
|
23
|
+
|
24
|
+
module Cosmos
|
25
|
+
class NoteModel < SortedModel
|
26
|
+
NOTE_TYPE = 'note'.freeze
|
27
|
+
PRIMARY_KEY = '__NOTE'.freeze
|
28
|
+
|
29
|
+
def self.pk(scope)
|
30
|
+
"#{scope}#{PRIMARY_KEY}"
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :stop, :color, :description, :type
|
34
|
+
|
35
|
+
# @param [String] scope - Cosmos scope to track event to
|
36
|
+
# @param [Integer] start - start of the event in seconds from Epoch
|
37
|
+
# @param [Integer] stop - stop of the event in seconds from Epoch
|
38
|
+
# @param [String] color - The event color
|
39
|
+
# @param [String] description - What the event is about
|
40
|
+
def initialize(
|
41
|
+
scope:,
|
42
|
+
start:,
|
43
|
+
stop:,
|
44
|
+
color: nil,
|
45
|
+
description:,
|
46
|
+
type: NOTE_TYPE,
|
47
|
+
updated_at: 0
|
48
|
+
)
|
49
|
+
super(start: start, scope: scope, updated_at: updated_at)
|
50
|
+
@start = start
|
51
|
+
@stop = stop
|
52
|
+
@color = color
|
53
|
+
@description = description
|
54
|
+
@type = type # For the as_json, from_json round trip
|
55
|
+
end
|
56
|
+
|
57
|
+
# Validates the instance variables: @start, @stop, @color, @description
|
58
|
+
def validate(update: false)
|
59
|
+
validate_start(update: update)
|
60
|
+
validate_stop()
|
61
|
+
validate_color()
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_stop()
|
65
|
+
unless @stop.is_a?(Integer)
|
66
|
+
raise SortedInputError.new "stop must be integer: #{@stop}"
|
67
|
+
end
|
68
|
+
if @stop.to_i < @start
|
69
|
+
raise SortedInputError.new "stop: #{@stop} must be >= start: #{@start}"
|
70
|
+
end
|
71
|
+
@stop = @stop.to_i
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_color()
|
75
|
+
if @color.nil?
|
76
|
+
@color = '#%06x' % (rand * 0xffffff)
|
77
|
+
end
|
78
|
+
unless @color =~ /(#*)([0-9,a-f,A-f]{6})/
|
79
|
+
raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
|
80
|
+
end
|
81
|
+
@color = "##{@color}" unless @color.start_with?('#')
|
82
|
+
end
|
83
|
+
|
84
|
+
# Update the Redis hash at primary_key based on the initial passed start
|
85
|
+
# The member is set to the JSON generated via calling as_json
|
86
|
+
def create(update: false)
|
87
|
+
validate(update: update)
|
88
|
+
@updated_at = Time.now.to_nsec_from_epoch
|
89
|
+
NoteModel.destroy(scope: @scope, start: update) if update
|
90
|
+
Store.zadd(@primary_key, @start, JSON.generate(as_json()))
|
91
|
+
if update
|
92
|
+
notify(kind: 'updated')
|
93
|
+
else
|
94
|
+
notify(kind: 'created')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Update the Redis hash at primary_key
|
99
|
+
def update(start:, stop:, color:, description:)
|
100
|
+
orig_start = @start
|
101
|
+
@start = start
|
102
|
+
@stop = stop
|
103
|
+
@color = color
|
104
|
+
@description = description
|
105
|
+
create(update: orig_start)
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Hash] generated from the NoteModel
|
109
|
+
def as_json
|
110
|
+
return {
|
111
|
+
'scope' => @scope,
|
112
|
+
'start' => @start,
|
113
|
+
'stop' => @stop,
|
114
|
+
'color' => @color,
|
115
|
+
'description' => @description,
|
116
|
+
'type' => NOTE_TYPE,
|
117
|
+
'updated_at' => @updated_at,
|
118
|
+
}
|
119
|
+
end
|
120
|
+
alias to_s as_json
|
121
|
+
end
|
122
|
+
end
|
@@ -32,6 +32,7 @@ require 'cosmos/models/tool_model'
|
|
32
32
|
require 'cosmos/models/widget_model'
|
33
33
|
require 'cosmos/models/microservice_model'
|
34
34
|
require 'tmpdir'
|
35
|
+
require 'tempfile'
|
35
36
|
|
36
37
|
module Cosmos
|
37
38
|
# Represents a COSMOS plugin that can consist of targets, interfaces, routers
|
@@ -41,6 +42,9 @@ module Cosmos
|
|
41
42
|
PRIMARY_KEY = 'cosmos_plugins'
|
42
43
|
|
43
44
|
attr_accessor :variables
|
45
|
+
attr_accessor :plugin_txt_lines
|
46
|
+
attr_accessor :needs_dependencies
|
47
|
+
|
44
48
|
|
45
49
|
# NOTE: The following three class methods are used by the ModelController
|
46
50
|
# and are reimplemented to enable various Model class methods to work
|
@@ -58,74 +62,103 @@ module Cosmos
|
|
58
62
|
|
59
63
|
# Called by the PluginsController to parse the plugin variables
|
60
64
|
# Doesn't actaully create the plugin during the phase
|
61
|
-
def self.install_phase1(gem_file_path, existing_variables
|
62
|
-
|
63
|
-
|
64
|
-
# Load gem to internal gem server
|
65
|
-
Cosmos::GemModel.put(gem_file_path, gem_install: false, scope: scope)
|
66
|
-
|
67
|
-
# Extract gem and process plugin.txt to determine what VARIABLEs need to be filled in
|
68
|
-
pkg = Gem::Package.new(gem_file_path)
|
65
|
+
def self.install_phase1(gem_file_path, existing_variables: nil, existing_plugin_txt_lines: nil, process_existing: false, scope:, validate_only: false)
|
66
|
+
gem_name = File.basename(gem_file_path).split("__")[0]
|
69
67
|
|
70
68
|
temp_dir = Dir.mktmpdir
|
69
|
+
tf = nil
|
71
70
|
begin
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
71
|
+
if File.exists?(gem_file_path)
|
72
|
+
# Load gem to internal gem server
|
73
|
+
Cosmos::GemModel.put(gem_file_path, gem_install: false, scope: scope) unless validate_only
|
74
|
+
else
|
75
|
+
gem_file_path = Cosmos::GemModel.get(temp_dir, gem_name)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Extract gem and process plugin.txt to determine what VARIABLEs need to be filled in
|
79
|
+
pkg = Gem::Package.new(gem_file_path)
|
80
|
+
|
81
|
+
if existing_plugin_txt_lines and process_existing
|
82
|
+
# This is only used in cosmos load when everything is known
|
83
|
+
plugin_txt_lines = existing_plugin_txt_lines
|
84
|
+
file_data = existing_plugin_txt_lines.join("\n")
|
85
|
+
tf = Tempfile.new("plugin.txt")
|
86
|
+
tf.write(file_data)
|
87
|
+
tf.close
|
88
|
+
plugin_txt_path = tf.path
|
89
|
+
else
|
90
|
+
# Otherwise we always process the new and return both
|
91
|
+
pkg.extract_files(temp_dir)
|
92
|
+
plugin_txt_path = File.join(temp_dir, 'plugin.txt')
|
93
|
+
plugin_text = File.read(plugin_txt_path)
|
94
|
+
plugin_txt_lines = []
|
95
|
+
plugin_text.each_line do |line|
|
96
|
+
plugin_txt_lines << line.chomp
|
95
97
|
end
|
98
|
+
end
|
99
|
+
|
100
|
+
parser = Cosmos::ConfigParser.new("http://cosmosc2.com")
|
96
101
|
|
97
|
-
|
98
|
-
|
102
|
+
# Phase 1 Gather Variables
|
103
|
+
variables = {}
|
104
|
+
parser.parse_file(plugin_txt_path,
|
105
|
+
false,
|
106
|
+
true,
|
107
|
+
false) do |keyword, params|
|
108
|
+
case keyword
|
109
|
+
when 'VARIABLE'
|
110
|
+
usage = "#{keyword} <Variable Name> <Default Value>"
|
111
|
+
parser.verify_num_parameters(2, nil, usage)
|
112
|
+
variable_name = params[0]
|
113
|
+
value = params[1..-1].join(" ")
|
114
|
+
variables[variable_name] = value
|
115
|
+
if existing_variables && existing_variables.key?(variable_name)
|
116
|
+
variables[variable_name] = existing_variables[variable_name]
|
117
|
+
end
|
118
|
+
# Ignore everything else during phase 1
|
119
|
+
end
|
99
120
|
end
|
121
|
+
|
122
|
+
model = PluginModel.new(name: gem_name, variables: variables, plugin_txt_lines: plugin_txt_lines, scope: scope)
|
123
|
+
result = model.as_json
|
124
|
+
result['existing_plugin_txt_lines'] = existing_plugin_txt_lines if existing_plugin_txt_lines and not process_existing and existing_plugin_txt_lines != result['plugin_txt_lines']
|
125
|
+
return result
|
100
126
|
ensure
|
101
127
|
FileUtils.remove_entry(temp_dir) if temp_dir and File.exist?(temp_dir)
|
128
|
+
tf.unlink if tf
|
102
129
|
end
|
103
130
|
end
|
104
131
|
|
105
132
|
# Called by the PluginsController to create the plugin
|
106
133
|
# Because this uses ERB it must be run in a seperate process from the API to
|
107
134
|
# prevent corruption and single require problems in the current proces
|
108
|
-
def self.install_phase2(
|
135
|
+
def self.install_phase2(plugin_hash, scope:, validate_only: false)
|
109
136
|
rubys3_client = Aws::S3::Client.new
|
110
137
|
|
111
138
|
# Ensure config bucket exists
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
139
|
+
unless validate_only
|
140
|
+
begin
|
141
|
+
rubys3_client.head_bucket(bucket: 'config')
|
142
|
+
rescue Aws::S3::Errors::NotFound
|
143
|
+
rubys3_client.create_bucket(bucket: 'config')
|
144
|
+
end
|
116
145
|
end
|
117
146
|
|
118
147
|
# Register plugin to aid in uninstall if install fails
|
119
|
-
|
120
|
-
plugin_model.
|
148
|
+
plugin_hash.delete("existing_plugin_txt_lines")
|
149
|
+
plugin_model = PluginModel.new(**(plugin_hash.transform_keys(&:to_sym)), scope: scope)
|
150
|
+
plugin_model.create unless validate_only
|
121
151
|
|
122
152
|
temp_dir = Dir.mktmpdir
|
123
153
|
begin
|
154
|
+
tf = nil
|
155
|
+
|
124
156
|
# Get the gem from local gem server
|
125
|
-
|
157
|
+
gem_name = plugin_hash['name'].split("__")[0]
|
158
|
+
gem_file_path = Cosmos::GemModel.get(temp_dir, gem_name)
|
126
159
|
|
127
160
|
# Actually install the gem now (slow)
|
128
|
-
Cosmos::GemModel.install(gem_file_path)
|
161
|
+
Cosmos::GemModel.install(gem_file_path, scope: scope)
|
129
162
|
|
130
163
|
# Extract gem contents
|
131
164
|
gem_path = File.join(temp_dir, "gem")
|
@@ -133,6 +166,11 @@ module Cosmos
|
|
133
166
|
pkg = Gem::Package.new(gem_file_path)
|
134
167
|
needs_dependencies = pkg.spec.runtime_dependencies.length > 0
|
135
168
|
pkg.extract_files(gem_path)
|
169
|
+
needs_dependencies = true if Dir.exist?(File.join(gem_path, 'lib'))
|
170
|
+
if needs_dependencies
|
171
|
+
plugin_model.needs_dependencies = true
|
172
|
+
plugin_model.update
|
173
|
+
end
|
136
174
|
|
137
175
|
# Temporarily add all lib folders from the gem to the end of the load path
|
138
176
|
load_dirs = []
|
@@ -145,7 +183,12 @@ module Cosmos
|
|
145
183
|
end
|
146
184
|
|
147
185
|
# Process plugin.txt file
|
148
|
-
|
186
|
+
file_data = plugin_hash['plugin_txt_lines'].join("\n")
|
187
|
+
tf = Tempfile.new("plugin.txt")
|
188
|
+
tf.write(file_data)
|
189
|
+
tf.close
|
190
|
+
plugin_txt_path = tf.path
|
191
|
+
variables = plugin_hash['variables']
|
149
192
|
if File.exist?(plugin_txt_path)
|
150
193
|
parser = Cosmos::ConfigParser.new("http://cosmosc2.com")
|
151
194
|
|
@@ -156,8 +199,8 @@ module Cosmos
|
|
156
199
|
# Ignore during phase 2
|
157
200
|
when 'TARGET', 'INTERFACE', 'ROUTER', 'MICROSERVICE', 'TOOL', 'WIDGET'
|
158
201
|
if current_model
|
159
|
-
current_model.create
|
160
|
-
current_model.deploy(gem_path, variables)
|
202
|
+
current_model.create unless validate_only
|
203
|
+
current_model.deploy(gem_path, variables, validate_only: validate_only)
|
161
204
|
current_model = nil
|
162
205
|
end
|
163
206
|
current_model = Cosmos.const_get((keyword.capitalize + 'Model').intern).handle_config(parser, keyword, params, plugin: plugin_model.name, needs_dependencies: needs_dependencies, scope: scope)
|
@@ -170,8 +213,8 @@ module Cosmos
|
|
170
213
|
end
|
171
214
|
end
|
172
215
|
if current_model
|
173
|
-
current_model.create
|
174
|
-
current_model.deploy(gem_path, variables)
|
216
|
+
current_model.create unless validate_only
|
217
|
+
current_model.deploy(gem_path, variables, validate_only: validate_only)
|
175
218
|
current_model = nil
|
176
219
|
end
|
177
220
|
end
|
@@ -182,21 +225,28 @@ module Cosmos
|
|
182
225
|
end
|
183
226
|
rescue => err
|
184
227
|
# Install failed - need to cleanup
|
185
|
-
plugin_model.destroy
|
228
|
+
plugin_model.destroy unless validate_only
|
186
229
|
raise err
|
187
230
|
ensure
|
188
231
|
FileUtils.remove_entry(temp_dir) if temp_dir and File.exist?(temp_dir)
|
232
|
+
tf.unlink if tf
|
189
233
|
end
|
234
|
+
|
235
|
+
return plugin_model.as_json
|
190
236
|
end
|
191
237
|
|
192
238
|
def initialize(
|
193
239
|
name:,
|
194
240
|
variables: {},
|
241
|
+
plugin_txt_lines: [],
|
242
|
+
needs_dependencies: false,
|
195
243
|
updated_at: nil,
|
196
244
|
scope:
|
197
245
|
)
|
198
246
|
super("#{scope}__#{PRIMARY_KEY}", name: name, updated_at: updated_at, scope: scope)
|
199
247
|
@variables = variables
|
248
|
+
@plugin_txt_lines = plugin_txt_lines
|
249
|
+
@needs_dependencies = ConfigParser.handle_true_false(needs_dependencies)
|
200
250
|
end
|
201
251
|
|
202
252
|
def create(update: false, force: false)
|
@@ -208,6 +258,8 @@ module Cosmos
|
|
208
258
|
{
|
209
259
|
'name' => @name,
|
210
260
|
'variables' => @variables,
|
261
|
+
'plugin_txt_lines' => @plugin_txt_lines,
|
262
|
+
'needs_dependencies' => @needs_dependencies,
|
211
263
|
'updated_at' => @updated_at
|
212
264
|
}
|
213
265
|
end
|
@@ -220,5 +272,13 @@ module Cosmos
|
|
220
272
|
end
|
221
273
|
end
|
222
274
|
end
|
275
|
+
|
276
|
+
# Reinstall
|
277
|
+
def restore
|
278
|
+
plugin_hash = self.as_json
|
279
|
+
plugin_hash['name'] = plugin_hash['name'].split("__")[0]
|
280
|
+
Cosmos::PluginModel.install_phase2(plugin_hash, scope: @scope)
|
281
|
+
@destroyed = false
|
282
|
+
end
|
223
283
|
end
|
224
284
|
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
require 'cosmos/version'
|
21
21
|
require 'cosmos/models/model'
|
22
22
|
require 'cosmos/models/microservice_model'
|
23
|
+
require 'cosmos/models/settings_model'
|
23
24
|
|
24
25
|
module Cosmos
|
25
26
|
class ScopeModel < Model
|
@@ -51,23 +52,7 @@ module Cosmos
|
|
51
52
|
def deploy(gem_path, variables)
|
52
53
|
seed_database()
|
53
54
|
|
54
|
-
|
55
|
-
microservice_name = "#{@scope}__CLEANUP__S3"
|
56
|
-
microservice = MicroserviceModel.new(
|
57
|
-
name: microservice_name,
|
58
|
-
cmd: ["ruby", "cleanup_microservice.rb", microservice_name],
|
59
|
-
work_dir: '/cosmos/lib/cosmos/microservices',
|
60
|
-
options: [
|
61
|
-
["SIZE", "20_000_000_000"], # Max Size to keep in S3
|
62
|
-
["DELAY", "300"], # Delay between size checks
|
63
|
-
["BUCKET", "logs"], # Bucket to monitor
|
64
|
-
["PREFIX", @scope + "/"], # Path into bucket to monitor
|
65
|
-
],
|
66
|
-
scope: @scope
|
67
|
-
)
|
68
|
-
microservice.create
|
69
|
-
microservice.deploy(gem_path, variables)
|
70
|
-
Logger.info "Configured microservice #{microservice_name}"
|
55
|
+
ConfigTopic.initialize_stream(@scope)
|
71
56
|
|
72
57
|
# COSMOS Log Microservice
|
73
58
|
microservice_name = "#{@scope}__COSMOS__LOG"
|
@@ -105,7 +90,7 @@ module Cosmos
|
|
105
90
|
Logger.info "Configured microservice #{microservice_name}"
|
106
91
|
|
107
92
|
# UNKNOWN CommandLog Microservice
|
108
|
-
|
93
|
+
Topic.initialize_streams(["#{@scope}__COMMAND__{UNKNOWN}__UNKNOWN"])
|
109
94
|
microservice_name = "#{@scope}__COMMANDLOG__UNKNOWN"
|
110
95
|
microservice = MicroserviceModel.new(
|
111
96
|
name: microservice_name,
|
@@ -125,7 +110,7 @@ module Cosmos
|
|
125
110
|
Logger.info "Configured microservice #{microservice_name}"
|
126
111
|
|
127
112
|
# UNKNOWN PacketLog Microservice
|
128
|
-
|
113
|
+
Topic.initialize_streams(["#{@scope}__TELEMETRY__{UNKNOWN}__UNKNOWN"])
|
129
114
|
microservice_name = "#{@scope}__PACKETLOG__UNKNOWN"
|
130
115
|
microservice = MicroserviceModel.new(
|
131
116
|
name: microservice_name,
|
@@ -146,8 +131,6 @@ module Cosmos
|
|
146
131
|
end
|
147
132
|
|
148
133
|
def undeploy
|
149
|
-
model = MicroserviceModel.get_model(name: "#{@scope}__CLEANUP__S3", scope: @scope)
|
150
|
-
model.destroy if model
|
151
134
|
model = MicroserviceModel.get_model(name: "#{@scope}__COSMOS__LOG", scope: @scope)
|
152
135
|
model.destroy if model
|
153
136
|
model = MicroserviceModel.get_model(name: "#{@scope}__NOTIFICATION__LOG", scope: @scope)
|
@@ -159,10 +142,12 @@ module Cosmos
|
|
159
142
|
end
|
160
143
|
|
161
144
|
def seed_database
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
145
|
+
setting = SettingsModel.get(name: 'source_url')
|
146
|
+
SettingsModel.set({ name: 'source_url', data: 'https://github.com/BallAerospace/COSMOS' }, scope: @scope) unless setting
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.limits_set(scope:)
|
150
|
+
Store.hget("#{scope}__cosmos_system", 'limits_set').intern
|
166
151
|
end
|
167
152
|
end
|
168
153
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# This program may also be used under the terms of a commercial or
|
17
|
+
# enterprise edition license of COSMOS if purchased from the
|
18
|
+
# copyright holder
|
19
|
+
|
20
|
+
require 'cosmos/models/model'
|
21
|
+
|
22
|
+
module Cosmos
|
23
|
+
class SettingsModel < Model
|
24
|
+
PRIMARY_KEY = 'cosmos__settings'
|
25
|
+
|
26
|
+
# NOTE: The following three class methods are used by the ModelController
|
27
|
+
# and are reimplemented to enable various Model class methods to work
|
28
|
+
def self.get(name:, scope: nil)
|
29
|
+
super(PRIMARY_KEY, name: name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.names(scope: nil)
|
33
|
+
super(PRIMARY_KEY)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.all(scope: nil)
|
37
|
+
super(PRIMARY_KEY)
|
38
|
+
end
|
39
|
+
# END NOTE
|
40
|
+
|
41
|
+
def initialize(name:, scope: nil, data:)
|
42
|
+
super(PRIMARY_KEY, name: name, scope: scope)
|
43
|
+
@data = data
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Hash] JSON encoding of this model
|
47
|
+
def as_json
|
48
|
+
{
|
49
|
+
'name' => @name,
|
50
|
+
'data' => @data,
|
51
|
+
'updated_at' => @updated_at
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|