openc3-cosmos-cmd-tlm-api/app/controllers/plugins_controller.rb
# encoding: ascii-8bit
# Copyright 2022 Ball Aerospace & Technologies Corp.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# Modified by OpenC3, Inc.
# All changes Copyright 2024, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.
require 'openc3/utilities/process_manager'
require 'openc3/models/plugin_model'
require 'fileutils'
require 'tmpdir'
class PluginsController < ModelController
def initialize
@model_class = OpenC3::PluginModel
end
# Add a new plugin
def create(update = false)
return unless authorization('admin')
file = params[:plugin]
if file
scope = sanitize_params([:scope])
return unless scope
scope = scope[0]
temp_dir = Dir.mktmpdir
begin
gem_file_path = temp_dir + '/' + file.original_filename
FileUtils.cp(file.tempfile.path, gem_file_path)
if @existing_model
result = OpenC3::PluginModel.install_phase1(gem_file_path, existing_variables: @existing_model['variables'], existing_plugin_txt_lines: @existing_model['plugin_txt_lines'], scope: scope)
else
result = OpenC3::PluginModel.install_phase1(gem_file_path, scope: scope)
end
render json: result
rescue Exception => error
render json: { status: 'error', message: error.message }, status: 500
logger.error(error.formatted)
ensure
FileUtils.remove_entry(temp_dir) if temp_dir and File.exist?(temp_dir)
end
else
logger.error("No file received")
render json: { status: 'error', message: "No file received" }, status: 500
end
end
def update
return unless authorization('admin')
# Grab the existing plugin we're updating so we can display existing variables
@existing_model = @model_class.get(name: params[:id], scope: params[:scope])
create(true)
end
def install
return unless authorization('admin')
begin
scope = sanitize_params([:scope])
return unless scope
scope = scope[0]
temp_dir = Dir.mktmpdir
plugin_hash_filename = Dir::Tmpname.create(['plugin-instance-', '.json']) {}
plugin_hash_file_path = File.join(temp_dir, File.basename(plugin_hash_filename))
File.open(plugin_hash_file_path, 'wb') do |file|
file.write(params[:plugin_hash])
end
gem_name = sanitize_params([:id])
return unless gem_name
gem_name = gem_name[0].split("__")[0]
result = OpenC3::ProcessManager.instance.spawn(
["ruby", "/openc3/bin/openc3cli", "load", gem_name, scope, plugin_hash_file_path, "force"], # force install
"plugin_install", params[:id], Time.now + 1.hour, temp_dir: temp_dir, scope: scope
)
render json: result.name
rescue Exception => error
logger.error(error.formatted)
render json: { status: 'error', message: error.message }, status: 500
end
end
def destroy
return unless authorization('admin')
begin
id, scope = sanitize_params([:id, :scope])
return unless id and scope
result = OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "unload", id, scope], "plugin_uninstall", id, Time.now + 1.hour, scope: scope)
render json: result.name
rescue Exception => error
logger.error(error.formatted)
render json: { status: 'error', message: error.message }, status: 500
end
end
end