openc3 5.0.11 → 5.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Guardfile +3 -0
- data/LICENSE.txt +7 -5
- data/README.md +11 -9
- data/Rakefile +3 -0
- data/bin/cstol_converter +3 -0
- data/bin/openc3cli +29 -18
- data/bin/rubysloc +3 -0
- data/data/config/screen.yaml +10 -2
- data/data/config/target.yaml +1 -1
- data/data/config/widgets.yaml +6 -6
- data/ext/mkrf_conf.rb +3 -0
- data/ext/openc3/ext/array/array.c +3 -0
- data/ext/openc3/ext/buffered_file/buffered_file.c +3 -0
- data/ext/openc3/ext/config_parser/config_parser.c +3 -0
- data/ext/openc3/ext/crc/crc.c +3 -0
- data/ext/openc3/ext/openc3_io/openc3_io.c +3 -0
- data/ext/openc3/ext/packet/packet.c +3 -0
- data/ext/openc3/ext/platform/platform.c +3 -0
- data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +3 -0
- data/ext/openc3/ext/string/string.c +3 -0
- data/ext/openc3/ext/structure/structure.c +3 -0
- data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +3 -0
- data/ext/openc3/ext/telemetry/telemetry.c +3 -0
- data/lib/cosmos.rb +3 -0
- data/lib/cosmosc2.rb +3 -0
- data/lib/openc3/accessors/accessor.rb +3 -0
- data/lib/openc3/accessors/binary_accessor.rb +3 -0
- data/lib/openc3/accessors/cbor_accessor.rb +3 -0
- data/lib/openc3/accessors/html_accessor.rb +3 -0
- data/lib/openc3/accessors/json_accessor.rb +4 -1
- data/lib/openc3/accessors/xml_accessor.rb +3 -0
- data/lib/openc3/accessors.rb +3 -0
- data/lib/openc3/api/api.rb +3 -0
- data/lib/openc3/api/authorized_api.rb +3 -0
- data/lib/openc3/api/cmd_api.rb +6 -3
- data/lib/openc3/api/config_api.rb +3 -0
- data/lib/openc3/api/interface_api.rb +6 -2
- data/lib/openc3/api/limits_api.rb +54 -61
- data/lib/openc3/api/router_api.rb +6 -3
- data/lib/openc3/api/settings_api.rb +3 -0
- data/lib/openc3/api/target_api.rb +3 -0
- data/lib/openc3/api/tlm_api.rb +27 -32
- data/lib/openc3/bridge/bridge.rb +3 -0
- data/lib/openc3/bridge/bridge_config.rb +3 -0
- data/lib/openc3/bridge/bridge_interface_thread.rb +3 -0
- data/lib/openc3/bridge/bridge_router_thread.rb +3 -0
- data/lib/openc3/ccsds/ccsds_packet.rb +3 -0
- data/lib/openc3/ccsds/ccsds_parser.rb +3 -0
- data/lib/openc3/config/config_parser.rb +3 -0
- data/lib/openc3/config/meta_config_parser.rb +3 -0
- data/lib/openc3/conversions/conversion.rb +3 -0
- data/lib/openc3/conversions/generic_conversion.rb +3 -0
- data/lib/openc3/conversions/packet_time_formatted_conversion.rb +3 -0
- data/lib/openc3/conversions/packet_time_seconds_conversion.rb +3 -0
- data/lib/openc3/conversions/polynomial_conversion.rb +3 -0
- data/lib/openc3/conversions/processor_conversion.rb +3 -0
- data/lib/openc3/conversions/received_count_conversion.rb +3 -0
- data/lib/openc3/conversions/received_time_formatted_conversion.rb +3 -0
- data/lib/openc3/conversions/received_time_seconds_conversion.rb +3 -0
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +3 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +3 -0
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +3 -0
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +3 -0
- data/lib/openc3/conversions.rb +3 -0
- data/lib/openc3/core_ext/array.rb +3 -0
- data/lib/openc3/core_ext/binding.rb +3 -0
- data/lib/openc3/core_ext/class.rb +3 -0
- data/lib/openc3/core_ext/exception.rb +3 -0
- data/lib/openc3/core_ext/file.rb +3 -0
- data/lib/openc3/core_ext/hash.rb +3 -0
- data/lib/openc3/core_ext/io.rb +3 -0
- data/lib/openc3/core_ext/kernel.rb +3 -0
- data/lib/openc3/core_ext/math.rb +3 -0
- data/lib/openc3/core_ext/matrix.rb +3 -0
- data/lib/openc3/core_ext/objectspace.rb +3 -0
- data/lib/openc3/core_ext/openc3_io.rb +3 -0
- data/lib/openc3/core_ext/range.rb +3 -0
- data/lib/openc3/core_ext/socket.rb +3 -0
- data/lib/openc3/core_ext/string.rb +3 -0
- data/lib/openc3/core_ext/stringio.rb +3 -0
- data/lib/openc3/core_ext/tempfile.rb +3 -0
- data/lib/openc3/core_ext/time.rb +3 -0
- data/lib/openc3/core_ext.rb +3 -0
- data/lib/openc3/interfaces/interface.rb +3 -0
- data/lib/openc3/interfaces/linc_interface.rb +3 -0
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/length_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/override_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/template_protocol.rb +3 -0
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +3 -0
- data/lib/openc3/interfaces/serial_interface.rb +3 -0
- data/lib/openc3/interfaces/simulated_target_interface.rb +3 -0
- data/lib/openc3/interfaces/stream_interface.rb +3 -0
- data/lib/openc3/interfaces/tcpip_client_interface.rb +3 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +3 -0
- data/lib/openc3/interfaces/udp_interface.rb +3 -0
- data/lib/openc3/interfaces.rb +3 -0
- data/lib/openc3/io/buffered_file.rb +3 -0
- data/lib/openc3/io/io_multiplexer.rb +8 -0
- data/lib/openc3/io/json_api_object.rb +5 -2
- data/lib/openc3/io/json_drb.rb +3 -0
- data/lib/openc3/io/json_drb_object.rb +5 -2
- data/lib/openc3/io/json_drb_rack.rb +3 -0
- data/lib/openc3/io/json_rpc.rb +8 -3
- data/lib/openc3/io/openc3_snmp.rb +3 -0
- data/lib/openc3/io/posix_serial_driver.rb +3 -0
- data/lib/openc3/io/raw_logger.rb +3 -0
- data/lib/openc3/io/raw_logger_pair.rb +3 -0
- data/lib/openc3/io/serial_driver.rb +3 -0
- data/lib/openc3/io/stderr.rb +3 -0
- data/lib/openc3/io/stdout.rb +3 -0
- data/lib/openc3/io/udp_sockets.rb +3 -0
- data/lib/openc3/io/win32_serial_driver.rb +3 -0
- data/lib/openc3/logs/buffered_packet_log_reader.rb +65 -0
- data/lib/openc3/logs/buffered_packet_log_writer.rb +120 -0
- data/lib/openc3/logs/log_writer.rb +95 -40
- data/lib/openc3/logs/packet_log_constants.rb +9 -0
- data/lib/openc3/logs/packet_log_reader.rb +34 -3
- data/lib/openc3/logs/packet_log_writer.rb +85 -18
- data/lib/openc3/logs/text_log_writer.rb +9 -5
- data/lib/openc3/logs.rb +8 -2
- data/lib/openc3/microservices/cleanup_microservice.rb +18 -18
- data/lib/openc3/microservices/decom_microservice.rb +30 -24
- data/lib/openc3/microservices/interface_microservice.rb +136 -91
- data/lib/openc3/microservices/log_microservice.rb +35 -13
- data/lib/openc3/microservices/microservice.rb +16 -14
- data/lib/openc3/microservices/plugin_microservice.rb +3 -1
- data/lib/openc3/microservices/reaction_microservice.rb +4 -1
- data/lib/openc3/microservices/reducer_microservice.rb +332 -149
- data/lib/openc3/microservices/router_microservice.rb +3 -0
- data/lib/openc3/microservices/text_log_microservice.rb +22 -7
- data/lib/openc3/microservices/timeline_microservice.rb +4 -1
- data/lib/openc3/microservices/trigger_group_microservice.rb +3 -0
- data/lib/openc3/models/activity_model.rb +3 -0
- data/lib/openc3/models/auth_model.rb +3 -0
- data/lib/openc3/models/cvt_model.rb +14 -5
- data/lib/openc3/models/environment_model.rb +3 -0
- data/lib/openc3/models/gem_model.rb +30 -51
- data/lib/openc3/models/info_model.rb +3 -0
- data/lib/openc3/models/interface_model.rb +3 -0
- data/lib/openc3/models/interface_status_model.rb +4 -1
- data/lib/openc3/models/metadata_model.rb +3 -0
- data/lib/openc3/models/metric_model.rb +3 -0
- data/lib/openc3/models/microservice_model.rb +9 -6
- data/lib/openc3/models/microservice_status_model.rb +4 -1
- data/lib/openc3/models/model.rb +3 -0
- data/lib/openc3/models/note_model.rb +3 -0
- data/lib/openc3/models/notification_model.rb +3 -0
- data/lib/openc3/models/ping_model.rb +3 -0
- data/lib/openc3/models/plugin_model.rb +20 -14
- data/lib/openc3/models/process_status_model.rb +4 -1
- data/lib/openc3/models/reaction_model.rb +3 -0
- data/lib/openc3/models/reducer_model.rb +31 -24
- data/lib/openc3/models/router_model.rb +3 -0
- data/lib/openc3/models/router_status_model.rb +3 -0
- data/lib/openc3/models/scope_model.rb +3 -4
- data/lib/openc3/models/settings_model.rb +3 -0
- data/lib/openc3/models/sorted_model.rb +3 -0
- data/lib/openc3/models/target_model.rb +61 -94
- data/lib/openc3/models/timeline_model.rb +4 -1
- data/lib/openc3/models/tool_config_model.rb +3 -0
- data/lib/openc3/models/tool_model.rb +11 -9
- data/lib/openc3/models/trigger_group_model.rb +3 -0
- data/lib/openc3/models/trigger_model.rb +3 -0
- data/lib/openc3/models/widget_model.rb +18 -11
- data/lib/openc3/operators/microservice_operator.rb +3 -0
- data/lib/openc3/operators/operator.rb +105 -34
- data/lib/openc3/packets/commands.rb +3 -0
- data/lib/openc3/packets/json_packet.rb +87 -14
- data/lib/openc3/packets/limits.rb +4 -1
- data/lib/openc3/packets/limits_response.rb +3 -0
- data/lib/openc3/packets/packet.rb +5 -1
- data/lib/openc3/packets/packet_config.rb +3 -0
- data/lib/openc3/packets/packet_item.rb +9 -3
- data/lib/openc3/packets/packet_item_limits.rb +3 -0
- data/lib/openc3/packets/parsers/format_string_parser.rb +3 -0
- data/lib/openc3/packets/parsers/limits_parser.rb +3 -0
- data/lib/openc3/packets/parsers/limits_response_parser.rb +3 -0
- data/lib/openc3/packets/parsers/packet_item_parser.rb +3 -0
- data/lib/openc3/packets/parsers/packet_parser.rb +3 -0
- data/lib/openc3/packets/parsers/processor_parser.rb +3 -0
- data/lib/openc3/packets/parsers/state_parser.rb +3 -0
- data/lib/openc3/packets/parsers/xtce_converter.rb +3 -0
- data/lib/openc3/packets/parsers/xtce_parser.rb +3 -0
- data/lib/openc3/packets/structure.rb +3 -0
- data/lib/openc3/packets/structure_item.rb +3 -0
- data/lib/openc3/packets/telemetry.rb +3 -0
- data/lib/openc3/processors/processor.rb +3 -0
- data/lib/openc3/processors/statistics_processor.rb +3 -0
- data/lib/openc3/processors/watermark_processor.rb +3 -0
- data/lib/openc3/processors.rb +3 -0
- data/lib/openc3/script/api_shared.rb +35 -6
- data/lib/openc3/script/calendar.rb +3 -0
- data/lib/openc3/script/commands.rb +3 -0
- data/lib/openc3/script/exceptions.rb +3 -0
- data/lib/openc3/script/extract.rb +3 -0
- data/lib/openc3/script/limits.rb +3 -24
- data/lib/openc3/script/script.rb +11 -7
- data/lib/openc3/script/script_runner.rb +3 -0
- data/lib/openc3/script/storage.rb +33 -16
- data/lib/openc3/script/suite.rb +3 -0
- data/lib/openc3/script/suite_results.rb +3 -0
- data/lib/openc3/script/suite_runner.rb +3 -0
- data/lib/openc3/script/telemetry.rb +43 -0
- data/lib/openc3/script.rb +3 -0
- data/lib/openc3/streams/serial_stream.rb +3 -0
- data/lib/openc3/streams/stream.rb +3 -0
- data/lib/openc3/streams/tcpip_client_stream.rb +3 -0
- data/lib/openc3/streams/tcpip_socket_stream.rb +3 -0
- data/lib/openc3/system/system.rb +23 -10
- data/lib/openc3/system/system_config.rb +3 -0
- data/lib/openc3/system/target.rb +3 -0
- data/lib/openc3/system.rb +3 -0
- data/lib/openc3/tools/cmd_tlm_server/api.rb +3 -0
- data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +3 -0
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +3 -0
- data/lib/openc3/tools/table_manager/table.rb +3 -0
- data/lib/openc3/tools/table_manager/table_config.rb +3 -0
- data/lib/openc3/tools/table_manager/table_item.rb +3 -0
- data/lib/openc3/tools/table_manager/table_item_parser.rb +3 -0
- data/lib/openc3/tools/table_manager/table_manager_core.rb +3 -0
- data/lib/openc3/tools/table_manager/table_parser.rb +3 -0
- data/lib/openc3/tools/test_runner/test.rb +3 -0
- data/lib/openc3/top_level.rb +3 -0
- data/lib/openc3/topics/autonomic_topic.rb +3 -0
- data/lib/openc3/topics/calendar_topic.rb +3 -0
- data/lib/openc3/topics/command_decom_topic.rb +4 -1
- data/lib/openc3/topics/command_topic.rb +6 -1
- data/lib/openc3/topics/config_topic.rb +3 -0
- data/lib/openc3/topics/interface_topic.rb +9 -2
- data/lib/openc3/topics/limits_event_topic.rb +144 -10
- data/lib/openc3/topics/notifications_topic.rb +3 -0
- data/lib/openc3/topics/router_topic.rb +10 -3
- data/lib/openc3/topics/telemetry_decom_topic.rb +26 -20
- data/lib/openc3/topics/telemetry_reduced_topics.rb +92 -0
- data/lib/openc3/topics/telemetry_topic.rb +5 -2
- data/lib/openc3/topics/timeline_topic.rb +3 -0
- data/lib/openc3/topics/topic.rb +3 -0
- data/lib/openc3/utilities/authentication.rb +3 -0
- data/lib/openc3/utilities/authorization.rb +3 -0
- data/lib/openc3/utilities/aws_bucket.rb +199 -0
- data/lib/openc3/utilities/bucket.rb +82 -0
- data/lib/openc3/utilities/bucket_file_cache.rb +264 -0
- data/lib/openc3/utilities/bucket_utilities.rb +109 -0
- data/lib/openc3/utilities/crc.rb +3 -0
- data/lib/openc3/utilities/csv.rb +3 -0
- data/lib/openc3/utilities/local_bucket.rb +28 -0
- data/lib/openc3/utilities/local_mode.rb +47 -61
- data/lib/openc3/utilities/logger.rb +7 -1
- data/lib/openc3/utilities/message_log.rb +7 -4
- data/lib/openc3/utilities/metric.rb +4 -1
- data/lib/openc3/utilities/open_telemetry.rb +96 -0
- data/lib/openc3/utilities/process_manager.rb +3 -0
- data/lib/openc3/utilities/quaternion.rb +3 -0
- data/lib/openc3/utilities/ruby_lex_utils.rb +3 -0
- data/lib/openc3/utilities/s3_autoload.rb +3 -3
- data/lib/openc3/utilities/simulated_target.rb +3 -0
- data/lib/openc3/utilities/sleeper.rb +3 -0
- data/lib/openc3/utilities/store.rb +3 -0
- data/lib/openc3/utilities/store_autoload.rb +30 -23
- data/lib/openc3/utilities/target_file.rb +70 -83
- data/lib/openc3/utilities/zip.rb +3 -0
- data/lib/openc3/utilities.rb +3 -0
- data/lib/openc3/version.rb +6 -6
- data/lib/openc3/win32/excel.rb +3 -0
- data/lib/openc3/win32/win32.rb +3 -0
- data/lib/openc3/win32/win32_main.rb +3 -0
- data/lib/openc3.rb +3 -0
- data/tasks/gemfile_stats.rake +3 -0
- data/tasks/spec.rake +3 -0
- data/templates/plugin-template/plugin.gemspec +1 -1
- metadata +112 -6
- data/lib/openc3/utilities/s3.rb +0 -220
- data/lib/openc3/utilities/s3_file_cache.rb +0 -274
@@ -0,0 +1,199 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 OpenC3, Inc.
|
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 file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
require 'openc3/utilities/bucket'
|
20
|
+
module Aws
|
21
|
+
autoload(:S3, 'openc3/utilities/s3_autoload.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
module OpenC3
|
25
|
+
class AwsBucket < Bucket
|
26
|
+
CREATE_CHECK_COUNT = 100 # 10 seconds
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@client = Aws::S3::Client.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def create(bucket)
|
33
|
+
unless exist?(bucket)
|
34
|
+
@client.create_bucket({ bucket: bucket })
|
35
|
+
count = 0
|
36
|
+
until exist?(bucket) or count > CREATE_CHECK_COUNT
|
37
|
+
sleep(0.1)
|
38
|
+
count += 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
bucket
|
42
|
+
end
|
43
|
+
|
44
|
+
def ensure_public(bucket)
|
45
|
+
policy = <<~EOL
|
46
|
+
{
|
47
|
+
"Version": "2012-10-17",
|
48
|
+
"Statement": [
|
49
|
+
{
|
50
|
+
"Action": [
|
51
|
+
"s3:GetBucketLocation",
|
52
|
+
"s3:ListBucket"
|
53
|
+
],
|
54
|
+
"Effect": "Allow",
|
55
|
+
"Principal": {
|
56
|
+
"AWS": [
|
57
|
+
"*"
|
58
|
+
]
|
59
|
+
},
|
60
|
+
"Resource": [
|
61
|
+
"arn:aws:s3:::#{bucket}"
|
62
|
+
],
|
63
|
+
"Sid": ""
|
64
|
+
},
|
65
|
+
{
|
66
|
+
"Action": [
|
67
|
+
"s3:GetObject"
|
68
|
+
],
|
69
|
+
"Effect": "Allow",
|
70
|
+
"Principal": {
|
71
|
+
"AWS": [
|
72
|
+
"*"
|
73
|
+
]
|
74
|
+
},
|
75
|
+
"Resource": [
|
76
|
+
"arn:aws:s3:::#{bucket}/*"
|
77
|
+
],
|
78
|
+
"Sid": ""
|
79
|
+
}
|
80
|
+
]
|
81
|
+
}
|
82
|
+
EOL
|
83
|
+
@client.put_bucket_policy({ bucket: bucket, policy: policy })
|
84
|
+
end
|
85
|
+
|
86
|
+
def exist?(bucket)
|
87
|
+
@client.head_bucket({ bucket: bucket })
|
88
|
+
true
|
89
|
+
rescue Aws::S3::Errors::NotFound
|
90
|
+
false
|
91
|
+
end
|
92
|
+
|
93
|
+
def delete(bucket)
|
94
|
+
if exist?(bucket)
|
95
|
+
@client.delete_bucket({ bucket: bucket })
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_object(bucket:, key:, path: nil)
|
100
|
+
if path
|
101
|
+
@client.get_object(bucket: bucket, key: key, response_target: path)
|
102
|
+
else
|
103
|
+
@client.get_object(bucket: bucket, key: key)
|
104
|
+
end
|
105
|
+
# If the key is not found return nil
|
106
|
+
rescue Aws::S3::Errors::NoSuchKey
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
110
|
+
def list_objects(bucket:, prefix: nil)
|
111
|
+
token = nil
|
112
|
+
result = []
|
113
|
+
while true
|
114
|
+
resp = @client.list_objects_v2(bucket: bucket, prefix: prefix, max_keys: 1000)
|
115
|
+
result.concat(resp.contents)
|
116
|
+
break unless resp.is_truncated
|
117
|
+
token = resp.next_continuation_token
|
118
|
+
end
|
119
|
+
# Array of objects with key and size methods
|
120
|
+
result
|
121
|
+
end
|
122
|
+
|
123
|
+
# Lists the directories under a specified path
|
124
|
+
def list_directories(bucket:, path:)
|
125
|
+
# Trailing slash is important in AWS S3 when listing files
|
126
|
+
# See https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Types/ListObjectsV2Output.html#common_prefixes-instance_method
|
127
|
+
if path[-1] != '/'
|
128
|
+
path += '/'
|
129
|
+
end
|
130
|
+
token = nil
|
131
|
+
result = []
|
132
|
+
while true
|
133
|
+
resp = @client.list_objects_v2({
|
134
|
+
bucket: bucket,
|
135
|
+
max_keys: 1000,
|
136
|
+
prefix: path,
|
137
|
+
delimiter: '/',
|
138
|
+
continuation_token: token
|
139
|
+
})
|
140
|
+
resp.common_prefixes.each do |item|
|
141
|
+
# If path was DEFAULT/targets_modified/ then the
|
142
|
+
# results look like DEFAULT/targets_modified/INST/
|
143
|
+
result << item.prefix.split('/')[-1]
|
144
|
+
end
|
145
|
+
break unless resp.is_truncated
|
146
|
+
token = resp.next_continuation_token
|
147
|
+
end
|
148
|
+
result
|
149
|
+
end
|
150
|
+
|
151
|
+
# put_object fires off the request to store but does not confirm
|
152
|
+
def put_object(bucket:, key:, body:, content_type: nil, cache_control: nil, metadata: nil)
|
153
|
+
@client.put_object(bucket: bucket, key: key, body: body,
|
154
|
+
content_type: content_type, cache_control: cache_control, metadata: metadata)
|
155
|
+
end
|
156
|
+
|
157
|
+
# @returns [Boolean] Whether the file exists
|
158
|
+
def check_object(bucket:, key:)
|
159
|
+
@client.wait_until(:object_exists,
|
160
|
+
{
|
161
|
+
bucket: bucket,
|
162
|
+
key: key
|
163
|
+
},
|
164
|
+
{
|
165
|
+
max_attempts: 30,
|
166
|
+
delay: 0.1, # seconds
|
167
|
+
}
|
168
|
+
)
|
169
|
+
true
|
170
|
+
rescue Aws::Waiters::Errors::TooManyAttemptsError
|
171
|
+
false
|
172
|
+
end
|
173
|
+
|
174
|
+
def delete_object(bucket:, key:)
|
175
|
+
@client.delete_object(bucket: bucket, key: key)
|
176
|
+
end
|
177
|
+
|
178
|
+
def delete_objects(bucket:, keys:)
|
179
|
+
@client.delete_objects(bucket: bucket, delete: { objects: keys.map {|key| { key: key } } })
|
180
|
+
end
|
181
|
+
|
182
|
+
def presigned_request(bucket:, key:, method:, internal: true)
|
183
|
+
s3_presigner = Aws::S3::Presigner.new
|
184
|
+
|
185
|
+
if internal
|
186
|
+
prefix = '/'
|
187
|
+
else
|
188
|
+
prefix = '/files/'
|
189
|
+
end
|
190
|
+
|
191
|
+
url, headers = s3_presigner.presigned_request(method, bucket: bucket, key: key)
|
192
|
+
return {
|
193
|
+
:url => prefix + url.split('/')[3..-1].join('/'),
|
194
|
+
:headers => headers,
|
195
|
+
:method => method.to_s.split('_')[0],
|
196
|
+
}
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 OpenC3, Inc.
|
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 file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
# Interface class implemented by each cloud provider: AWS, GCS, Azure
|
20
|
+
module OpenC3
|
21
|
+
class Bucket
|
22
|
+
def self.getClient
|
23
|
+
raise 'OPENC3_CLOUD environment variable is required' unless ENV['OPENC3_CLOUD']
|
24
|
+
# Base is AwsBucket which works with MINIO, Enterprise implements additional
|
25
|
+
bucket_class = ENV['OPENC3_CLOUD'].capitalize + 'Bucket'
|
26
|
+
klass = OpenC3.require_class('openc3/utilities/'+bucket_class.class_name_to_filename)
|
27
|
+
klass.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
# Setup the client instance
|
32
|
+
end
|
33
|
+
|
34
|
+
def create(bucket)
|
35
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
36
|
+
end
|
37
|
+
|
38
|
+
def ensure_public(bucket)
|
39
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
40
|
+
end
|
41
|
+
|
42
|
+
def exist?(bucket)
|
43
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(bucket)
|
47
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_object(bucket:, key:, path: nil)
|
51
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
52
|
+
end
|
53
|
+
|
54
|
+
def list_objects(bucket:, prefix: nil)
|
55
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
56
|
+
end
|
57
|
+
|
58
|
+
def list_directories(bucket:, path:)
|
59
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
60
|
+
end
|
61
|
+
|
62
|
+
def put_object(bucket:, key:, body:, content_type: nil, cache_control: nil, metadata: nil)
|
63
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_object(bucket:, key:)
|
67
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_object(bucket:, key:)
|
71
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete_objects(bucket:, keys:)
|
75
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
76
|
+
end
|
77
|
+
|
78
|
+
def presigned_request(bucket:, key:, method:, internal: true)
|
79
|
+
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,264 @@
|
|
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
|
+
# Modified by OpenC3, Inc.
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
18
|
+
# All Rights Reserved
|
19
|
+
#
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
|
+
# if purchased from OpenC3, Inc.
|
22
|
+
|
23
|
+
require 'fileutils'
|
24
|
+
require 'tmpdir'
|
25
|
+
require 'openc3'
|
26
|
+
require 'openc3/utilities/bucket_utilities'
|
27
|
+
require 'openc3/utilities/bucket'
|
28
|
+
|
29
|
+
class BucketFile
|
30
|
+
MAX_AGE_SECONDS = 3600 * 4 # 4 hours
|
31
|
+
|
32
|
+
attr_reader :bucket_path
|
33
|
+
attr_reader :local_path
|
34
|
+
attr_reader :reservation_count
|
35
|
+
attr_reader :size
|
36
|
+
attr_reader :error
|
37
|
+
attr_reader :topic_prefix
|
38
|
+
attr_reader :init_time
|
39
|
+
attr_accessor :priority
|
40
|
+
|
41
|
+
def initialize(bucket_path, client = nil)
|
42
|
+
@bucket = client
|
43
|
+
unless @bucket
|
44
|
+
@bucket = OpenC3::Bucket.getClient()
|
45
|
+
end
|
46
|
+
@bucket_path = bucket_path
|
47
|
+
@local_path = nil
|
48
|
+
@reservation_count = 0
|
49
|
+
@size = 0
|
50
|
+
@priority = 0
|
51
|
+
@error = nil
|
52
|
+
@init_time = Time.now
|
53
|
+
@mutex = Mutex.new
|
54
|
+
path_split = @bucket_path.split("/")
|
55
|
+
scope = path_split[0].to_s.upcase
|
56
|
+
stream_mode = path_split[1].to_s.split("_")[0].to_s.upcase
|
57
|
+
if stream_mode == 'REDUCED'
|
58
|
+
stream_mode << '_' << path_split[1].to_s.split("_")[1].to_s.upcase
|
59
|
+
end
|
60
|
+
cmd_or_tlm = path_split[2].to_s.upcase
|
61
|
+
target_name = path_split[3].to_s.upcase
|
62
|
+
if stream_mode == 'RAW'
|
63
|
+
type = (@cmd_or_tlm == 'CMD') ? 'COMMAND' : 'TELEMETRY'
|
64
|
+
else
|
65
|
+
if stream_mode == 'DECOM'
|
66
|
+
type = (@cmd_or_tlm == 'CMD') ? 'DECOMCMD' : 'DECOM'
|
67
|
+
else
|
68
|
+
type = stream_mode # REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY
|
69
|
+
end
|
70
|
+
end
|
71
|
+
@topic_prefix = "#{scope}__#{type}__{#{target_name}}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def retrieve(client = @bucket, uncompress = true)
|
75
|
+
@mutex.synchronize do
|
76
|
+
local_path = "#{BucketFileCache.instance.cache_dir}/#{File.basename(@bucket_path)}"
|
77
|
+
unless File.exist?(local_path)
|
78
|
+
OpenC3::Logger.debug "Retrieving #{@bucket_path} from logs bucket"
|
79
|
+
client.get_object(bucket: "logs", key: @bucket_path, path: local_path)
|
80
|
+
if File.exist?(local_path)
|
81
|
+
basename = File.basename(local_path)
|
82
|
+
if uncompress and File.extname(basename) == ".gz"
|
83
|
+
uncompressed = OpenC3::BucketUtilities.uncompress_file(local_path)
|
84
|
+
File.delete(local_path)
|
85
|
+
local_path = uncompressed
|
86
|
+
end
|
87
|
+
@size = File.size(local_path)
|
88
|
+
@local_path = local_path
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
rescue => err
|
95
|
+
@error = err
|
96
|
+
OpenC3::Logger.error "Failed to retrieve #{@bucket_path}\n#{err.formatted}"
|
97
|
+
raise err
|
98
|
+
end
|
99
|
+
|
100
|
+
def reserve
|
101
|
+
@mutex.synchronize { @reservation_count += 1 }
|
102
|
+
return retrieve()
|
103
|
+
end
|
104
|
+
|
105
|
+
def unreserve
|
106
|
+
@mutex.synchronize do
|
107
|
+
@reservation_count -= 1
|
108
|
+
delete() if @reservation_count <= 0
|
109
|
+
return @reservation_count
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def age_check
|
114
|
+
@mutex.synchronize do
|
115
|
+
if (Time.now - @init_time) > MAX_AGE_SECONDS and @reservation_count <= 0
|
116
|
+
delete()
|
117
|
+
return true
|
118
|
+
else
|
119
|
+
return false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# private
|
125
|
+
|
126
|
+
def delete
|
127
|
+
if @local_path and File.exist?(@local_path)
|
128
|
+
File.delete(@local_path)
|
129
|
+
@local_path = nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class BucketFileCache
|
135
|
+
MAX_DISK_USAGE = (ENV['OPENC3_BUCKET_FILE_CACHE_SIZE'] || 20_000_000_000).to_i # Default 20 GB
|
136
|
+
CHECK_TIME_SECONDS = 3600
|
137
|
+
|
138
|
+
attr_reader :cache_dir
|
139
|
+
|
140
|
+
@@instance = nil
|
141
|
+
@@mutex = Mutex.new
|
142
|
+
|
143
|
+
def self.instance
|
144
|
+
return @@instance if @@instance
|
145
|
+
@@mutex.synchronize do
|
146
|
+
@@instance ||= BucketFileCache.new
|
147
|
+
end
|
148
|
+
@@instance
|
149
|
+
end
|
150
|
+
|
151
|
+
def initialize
|
152
|
+
@bucket = OpenC3::Bucket.getClient()
|
153
|
+
|
154
|
+
# Create local file cache location
|
155
|
+
@cache_dir = Dir.mktmpdir
|
156
|
+
FileUtils.mkdir_p(@cache_dir)
|
157
|
+
at_exit do
|
158
|
+
FileUtils.remove_dir(@cache_dir, true)
|
159
|
+
end
|
160
|
+
|
161
|
+
@current_disk_usage = 0
|
162
|
+
@queued_bucket_files = []
|
163
|
+
@bucket_file_hash = {}
|
164
|
+
|
165
|
+
@thread = Thread.new do
|
166
|
+
client = OpenC3::Bucket.getClient()
|
167
|
+
while true
|
168
|
+
check_time = Time.now + CHECK_TIME_SECONDS # Check for aged out files periodically
|
169
|
+
if @queued_bucket_files.length > 0 and @current_disk_usage < MAX_DISK_USAGE
|
170
|
+
@@mutex.synchronize do
|
171
|
+
bucket_file = @queued_bucket_files.shift
|
172
|
+
end
|
173
|
+
begin
|
174
|
+
retrieved = bucket_file.retrieve(client)
|
175
|
+
@@mutex.synchronize do
|
176
|
+
@current_disk_usage += bucket_file.size if retrieved
|
177
|
+
end
|
178
|
+
rescue
|
179
|
+
# Might have been deleted
|
180
|
+
end
|
181
|
+
sleep(0.01) # Small throttle
|
182
|
+
else
|
183
|
+
# Nothing to do or disk full
|
184
|
+
if Time.now > check_time
|
185
|
+
check_time = Time.now + CHECK_TIME_SECONDS
|
186
|
+
# Delete any files that aren't reserved and are old
|
187
|
+
removed_files = []
|
188
|
+
@bucket_file_hash.each do |bucket_path, bucket_file|
|
189
|
+
deleted = bucket_file.age_check
|
190
|
+
if deleted
|
191
|
+
removed_files << bucket_path
|
192
|
+
@current_disk_usage -= bucket_file.size
|
193
|
+
end
|
194
|
+
end
|
195
|
+
removed_files.each do |bucket_path|
|
196
|
+
@bucket_file_hash.delete(bucket_path)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
sleep(1)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
rescue => err
|
203
|
+
OpenC3::Logger.error "BucketFileCache thread unexpectedly died\n#{err.formatted}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.hint(bucket_paths)
|
208
|
+
return instance().hint(bucket_paths)
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.reserve(bucket_path)
|
212
|
+
return instance().reserve(bucket_path)
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.unreserve(bucket_path)
|
216
|
+
return instance().unreserve(bucket_path)
|
217
|
+
end
|
218
|
+
|
219
|
+
def hint(bucket_paths)
|
220
|
+
@@mutex.synchronize do
|
221
|
+
bucket_paths.each_with_index do |bucket_path, index|
|
222
|
+
bucket_file = create_bucket_file(bucket_path)
|
223
|
+
bucket_file.priority = index
|
224
|
+
end
|
225
|
+
@queued_bucket_files.sort! {|file1, file2| file1.priority <=> file2.priority}
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def reserve(bucket_path)
|
230
|
+
@@mutex.synchronize do
|
231
|
+
bucket_file = create_bucket_file(bucket_path)
|
232
|
+
retrieved = bucket_file.reserve
|
233
|
+
@current_disk_usage += bucket_file.size if retrieved
|
234
|
+
@queued_bucket_files.delete(bucket_file)
|
235
|
+
return bucket_file
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def unreserve(bucket_path)
|
240
|
+
@@mutex.synchronize do
|
241
|
+
bucket_file = @bucket_file_hash[bucket_path]
|
242
|
+
if bucket_file
|
243
|
+
bucket_file.unreserve
|
244
|
+
if bucket_file.reservation_count <= 0 and !@queued_bucket_files.include?(bucket_file)
|
245
|
+
@current_disk_usage -= bucket_file.size
|
246
|
+
@bucket_file_hash.delete(bucket_file)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# Private
|
253
|
+
|
254
|
+
def create_bucket_file(bucket_path)
|
255
|
+
bucket_file = @bucket_file_hash[bucket_path]
|
256
|
+
unless bucket_file
|
257
|
+
bucket_file = BucketFile.new(bucket_path)
|
258
|
+
@queued_bucket_files << bucket_file
|
259
|
+
@bucket_file_hash[bucket_path] = bucket_file
|
260
|
+
end
|
261
|
+
return bucket_file
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
@@ -0,0 +1,109 @@
|
|
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
|
+
# Modified by OpenC3, Inc.
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
18
|
+
# All Rights Reserved
|
19
|
+
#
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
|
+
# if purchased from OpenC3, Inc.
|
22
|
+
|
23
|
+
require 'openc3/utilities/bucket'
|
24
|
+
require 'openc3/models/reducer_model'
|
25
|
+
require 'zlib'
|
26
|
+
|
27
|
+
module OpenC3
|
28
|
+
class BucketUtilities
|
29
|
+
def self.list_files_before_time(bucket, prefix, time)
|
30
|
+
client = Bucket.getClient
|
31
|
+
oldest_list = []
|
32
|
+
|
33
|
+
# Return nothing if bucket doesn't exist (it won't at the very beginning)
|
34
|
+
unless client.exist?(bucket)
|
35
|
+
return oldest_list
|
36
|
+
end
|
37
|
+
|
38
|
+
next_folder = false
|
39
|
+
resp = client.list_objects(bucket: bucket, prefix: prefix)
|
40
|
+
resp.each do |item|
|
41
|
+
t = File.basename(item.key).split('__')[1]
|
42
|
+
file_end_time = Time.utc(t[0..3], t[4..5], t[6..7], t[8..9], t[10..11], t[12..13])
|
43
|
+
if file_end_time < time
|
44
|
+
oldest_list << item.key
|
45
|
+
else
|
46
|
+
break
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return oldest_list
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.move_log_file_to_bucket(filename, bucket_key, metadata: {})
|
53
|
+
Thread.new do
|
54
|
+
client = Bucket.getClient
|
55
|
+
|
56
|
+
zipped = compress_file(filename)
|
57
|
+
bucket_key = bucket_key + '.gz'
|
58
|
+
File.open(zipped, 'rb') do |read_file|
|
59
|
+
client.put_object(bucket: ENV['OPENC3_LOGS_BUCKET'], key: bucket_key, body: read_file, metadata: metadata)
|
60
|
+
end
|
61
|
+
Logger.debug "wrote #{ENV['OPENC3_LOGS_BUCKET']}/#{bucket_key}"
|
62
|
+
ReducerModel.add_file(bucket_key) # Record the new file for data reduction
|
63
|
+
|
64
|
+
File.delete(zipped)
|
65
|
+
File.delete(filename)
|
66
|
+
rescue => err
|
67
|
+
Logger.error("Error saving log file to bucket: #{filename}\n#{err.formatted}")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.get_cache_control(filename)
|
72
|
+
# Allow caching for files that have a filename versioning strategy
|
73
|
+
has_version_number = /(-|_|\.)\d+(-|_|\.)\d+(-|_|\.)\d+\./.match(filename)
|
74
|
+
has_content_hash = /\.[a-f0-9]{20}\./.match(filename)
|
75
|
+
return nil if has_version_number or has_content_hash
|
76
|
+
return 'no-cache'
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.compress_file(filename, chunk_size = 50_000_000)
|
80
|
+
zipped = "#{filename}.gz"
|
81
|
+
|
82
|
+
Zlib::GzipWriter.open(zipped) do |gz|
|
83
|
+
gz.mtime = File.mtime(filename)
|
84
|
+
gz.orig_name = filename
|
85
|
+
File.open(filename, 'rb') do |file|
|
86
|
+
while chunk = file.read(chunk_size) do
|
87
|
+
gz.write(chunk)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
return zipped
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.uncompress_file(filename, chunk_size = 50_000_000)
|
96
|
+
unzipped = filename[0..-4] # Drop .gz
|
97
|
+
|
98
|
+
Zlib::GzipReader.open(filename) do |gz|
|
99
|
+
File.open(unzipped, 'wb') do |file|
|
100
|
+
while chunk = gz.read(chunk_size)
|
101
|
+
file.write(chunk)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
return unzipped
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/openc3/utilities/crc.rb
CHANGED
@@ -16,6 +16,9 @@
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
|
+
#
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
|
+
# if purchased from OpenC3, Inc.
|
19
22
|
|
20
23
|
require 'openc3/ext/crc' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
|
21
24
|
|
data/lib/openc3/utilities/csv.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 OpenC3, Inc.
|
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 file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
require 'openc3/utilities/aws_bucket'
|
20
|
+
|
21
|
+
module OpenC3
|
22
|
+
# This class exists simply to enable the following code in bucket.rb
|
23
|
+
# bucket_class = ENV['OPENC3_CLOUD'].capitalize + 'Bucket'
|
24
|
+
# So when the OPENC3_CLOUD var is set to 'local' this file is used
|
25
|
+
# The local code uses Minio which is identical to the Aws APIs
|
26
|
+
class LocalBucket < AwsBucket
|
27
|
+
end
|
28
|
+
end
|