Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lint fixup #3154

Merged
merged 2 commits into from
Nov 9, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 141 additions & 129 deletions apps/dashboard/app/models/batch_connect/app.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require "smart_attributes"
# frozen_string_literal: true

require 'smart_attributes'

module BatchConnect
# This is the model representing a batch connect app. It's mostly a data object
Expand All @@ -23,15 +25,15 @@ class << self
# @param token [String] the token
# @return [App] generated object
def from_token(token)
type, *app = token.split("/")
type, *app = token.split('/')
case type
when "dev"
when 'dev'
name, sub_app = app
router = DevRouter.new(name)
when "usr"
when 'usr'
owner, name, sub_app = app
router = UsrRouter.new(name, owner)
else # "sys"
else # "sys"
name, sub_app = app
router = SysRouter.new(name)
end
Expand All @@ -44,13 +46,13 @@ def from_token(token)
# @param sub_app [String, nil] sub app
def initialize(router:, sub_app: nil)
@router = router
@sub_app = sub_app && sub_app.to_s
@sub_app = sub_app&.to_s
end

# Generate a token from this object
# @return [String] token
def token
[router.token, sub_app].compact.join("/")
[router.token, sub_app].compact.join('/')
end

# Get the token for this app, excluding the subapp
Expand All @@ -71,7 +73,7 @@ def sub_app_root
if Configuration.load_external_bc_config? && router.type == :sys && global_sub_app_root.directory?
global_sub_app_root
else
root.join("local")
root.join('local')
end
end

Expand Down Expand Up @@ -134,26 +136,26 @@ def metadata
def link
OodAppLink.new(
# FIXME: better to use default_title and "" description
title: title,
title: title,
description: description,
url: url,
icon_uri: icon_uri,
caption: caption,
new_tab: false,
data: preset? ? { 'method': 'post' } : {},
tile: tile
url: url,
icon_uri: icon_uri,
caption: caption,
new_tab: false,
data: preset? ? { 'method': 'post' } : {},
tile: tile
)
end

# The clusters the batch connect app is configured to use
# @return [Array<String>, []] the clusters the app wants to use
def configured_clusters
Array.wrap(form_config.fetch(:cluster, nil))
.select { |c| !c.to_s.strip.empty? }
.map { |c| c.to_s.strip }
.compact
.reject { |c| c.to_s.strip.empty? }
.map { |c| c.to_s.strip }
.compact
end

# Read in context from cache file if cache is disabled and context.json exist
def update_session_with_cache(session_context, cache_file)
cache = cache_file.file? ? JSON.parse(cache_file.read) : {}
Expand All @@ -163,12 +165,11 @@ def update_session_with_cache(session_context, cache_file)
end

def delete_cached_cluster?(cached_cluster)

# if you've cached a cluster that no longer exists
!OodAppkit.clusters.include?(cached_cluster) ||
# OR the app only has 1 cluster, and it's changed since the previous cluster was cached.
# I.e., admin wants to override what you've cached.
(self.clusters.size == 1 && self.clusters[0] != cached_cluster)
(clusters.size == 1 && clusters[0] != cached_cluster)
end

# The clusters that the batch connect app can use. It's a combination
Expand Down Expand Up @@ -212,12 +213,12 @@ def validation_reason
return @validation_reason if @validation_reason

if configured_clusters.empty?
"This app does not specify any cluster."
'This app does not specify any cluster.'
elsif clusters.empty?
"This app requires clusters that do not exist " +
"or you do not have access to."
'This app requires clusters that do not exist ' \
'or you do not have access to.'
else
""
''
end
end

Expand All @@ -236,7 +237,9 @@ def attributes
attribute_opts = { value: attribute_opts, fixed: true } unless attribute_opts.is_a?(Hash)

# Hide resolution if not using native vnc clients
attribute_opts = { value: nil, fixed: true } if attribute_id.to_s == "bc_vnc_resolution" && !ENV["ENABLE_NATIVE_VNC"]
if attribute_id.to_s == 'bc_vnc_resolution' && !ENV['ENABLE_NATIVE_VNC']
attribute_opts = { value: nil, fixed: true }
end

SmartAttributes::AttributeFactory.build(attribute_id, attribute_opts)
end
Expand Down Expand Up @@ -281,22 +284,22 @@ def submit_opts(session_context, fmt: nil, staged_root: nil)
# View used for session if it exists
# @return [String, nil] session view
def session_view
file = root.join("view.html.erb")
file = root.join('view.html.erb')
file.read if file.file?
end

# View used for session info if it exists
# @return [String, nil] session info
def session_info_view
@session_info_view ||= Pathname.new(root).glob("info.{md,html}.erb").find(&:file?).try(:read)
rescue
@session_info_view ||= Pathname.new(root).glob('info.{md,html}.erb').find(&:file?).try(:read)
rescue StandardError
nil
end

# Paths to custom javascript files
# @return [Pathname] paths to custom javascript files that exist
def custom_javascript_files
files = [root.join("form.js")]
files = [root.join('form.js')]
files << sub_app_root.join("#{sub_app}.js")
files.select(&:file?)
end
Expand Down Expand Up @@ -333,121 +336,130 @@ def cache_file

private

def url
helpers = Rails.application.routes.url_helpers
def url
helpers = Rails.application.routes.url_helpers

if preset?
helpers.batch_connect_session_contexts_path(token: token)
else
helpers.new_batch_connect_session_context_path(token: token)
end
if preset?
helpers.batch_connect_session_contexts_path(token: token)
else
helpers.new_batch_connect_session_context_path(token: token)
end
end

def cfg_to_clusters(config)
c = OodAppkit.clusters[config.to_sym] || nil
return [c] unless c.nil?
def cfg_to_clusters(config)
c = OodAppkit.clusters[config.to_sym] || nil
return [c] unless c.nil?

# cluster may be a glob at this point
OodAppkit.clusters.select do |cluster|
File.fnmatch(config, cluster.id.to_s, File::FNM_EXTGLOB)
end
# cluster may be a glob at this point
OodAppkit.clusters.select do |cluster|
File.fnmatch(config, cluster.id.to_s, File::FNM_EXTGLOB)
end
end

def build_sub_app_list
return [self] unless sub_app_root.directory? && sub_app_root.readable? && sub_app_root.executable?
list = sub_app_root.children.select(&:file?).map do |f|
root = f.dirname
name = f.basename.to_s.split(".").first
file = form_file(root: root, name: name)
self.class.new(router: router, sub_app: name) if f == file
end.compact
list.empty? ? [self] : list.sort_by(&:sub_app)
end
def build_sub_app_list
return [self] unless sub_app_root.directory? && sub_app_root.readable? && sub_app_root.executable?

# Path to file describing form hash
def form_file(root:, name: "form")
%W(#{name}.yml.erb #{name}.yml).map { |f| root.join(f) }.select(&:file?).first
end
list = sub_app_root.children.select(&:file?).map do |f|
root = f.dirname
name = f.basename.to_s.split('.').first
file = form_file(root: root, name: name)
self.class.new(router: router, sub_app: name) if f == file
end.compact
list.empty? ? [self] : list.sort_by(&:sub_app)
end

# Path to file describing submission hash
def submit_file(root:, paths: %w(submit.yml.erb submit.yml))
Array.wrap(paths).compact.map { |f| root.join(f) }.select(&:file?).first
end
# Path to file describing form hash
def form_file(root:, name: 'form')
["#{name}.yml.erb", "#{name}.yml"].map { |f| root.join(f) }.select(&:file?).first
end

# Parse an ERB and Yaml file
def read_yaml_erb(path:, binding: nil)
contents = path.read
contents = render_erb_file(path: path, contents: contents, binding: binding) if path.extname == ".erb"
YAML.safe_load(contents).to_h.deep_symbolize_keys
end
# Path to file describing submission hash
# rubocop:disable Style/WordArray - solargraph has a bug with ['arrays', 'like', 'this']
def submit_file(root:, paths: %w[submit.yml.erb submit.yml])
# rubocop:enable Style/WordArray
Array.wrap(paths).compact.map { |f| root.join(f) }.select(&:file?).first
end

# pure function to render erb, properly setting the filename attribute
# before rendering
def render_erb_file(path:, contents:, binding:)
erb = ERB.new(contents, trim_mode: "-")
erb.filename = path.to_s
erb.result(binding)
end
# Parse an ERB and Yaml file
def read_yaml_erb(path:, binding: nil)
contents = path.read
contents = render_erb_file(path: path, contents: contents, binding: binding) if path.extname == '.erb'
YAML.safe_load(contents).to_h.deep_symbolize_keys
end

# Hash describing the full form object
def form_config(binding: nil)
return @form_config if @form_config

raise AppNotFound, "This app does not exist under the directory '#{root}'" unless root.directory?
file = form_file(root: root)
raise AppNotFound, "This app does not supply a form file under the directory '#{root}'" unless file
hsh = read_yaml_erb(path: file, binding: binding)
if sub_app
file = form_file(root: sub_app_root, name: sub_app)
raise AppNotFound, "This app does not supply a sub app form file under the directory '#{sub_app_root}'" unless file
hsh = hsh.deep_merge read_yaml_erb(path: file, binding: binding)
end
@form_config = hsh
rescue AppNotFound => e
@validation_reason = e.message
return {}
rescue StandardError, Exception => e
@validation_reason = "#{e.class.name}: #{e.message}"
return {}
end
# pure function to render erb, properly setting the filename attribute
# before rendering
def render_erb_file(path:, contents:, binding:)
erb = ERB.new(contents, trim_mode: '-')
erb.filename = path.to_s
erb.result(binding)
end

# Hash describing the full submission properties
def submit_config(binding: nil)
return @submit_config if @submit_config
# Hash describing the full form object
def form_config(binding: nil)
return @form_config if @form_config

file = submit_file(root: root)
hsh = file ? read_yaml_erb(path: file, binding: binding) : {}
if path = form_config.fetch(:submit, nil)
file = submit_file(root: sub_app_root, paths: path)
hsh = hsh.deep_merge read_yaml_erb(path: file, binding: binding) if file
end
@submit_config = hsh
end
raise AppNotFound, "This app does not exist under the directory '#{root}'" unless root.directory?

# The OOD app object describing this app
def ood_app
@ood_app ||= OodApp.new(router)
end
file = form_file(root: root)
raise AppNotFound, "This app does not supply a form file under the directory '#{root}'" unless file

# add a widget for choosing the cluster if one doesn't already exist
# and if users aren't defining they're own form.cluster and attributes.cluster
def add_cluster_widget(attributes, attribute_list)
return unless clusters.any?

attribute_list.prepend("cluster") unless attribute_list.include?("cluster")

if clusters.size > 1
attributes[:cluster] = {
widget: "select",
label: "Cluster",
options: clusters.map(&:id)
}
else
attributes[:cluster] = {
value: clusters.first.id.to_s,
fixed: true
}
hsh = read_yaml_erb(path: file, binding: binding)
if sub_app
file = form_file(root: sub_app_root, name: sub_app)
unless file
msg = "This app does not supply a sub app form file under the directory '#{sub_app_root}'"
raise AppNotFound, msg
end

hsh = hsh.deep_merge read_yaml_erb(path: file, binding: binding)
end
@form_config = hsh
rescue AppNotFound => e
@validation_reason = e.message
{}
rescue StandardError, Exception => e
@validation_reason = "#{e.class.name}: #{e.message}"
{}
end

# Hash describing the full submission properties
def submit_config(binding: nil)
return @submit_config if @submit_config

file = submit_file(root: root)
hsh = file ? read_yaml_erb(path: file, binding: binding) : {}
if path = form_config.fetch(:submit, nil)
file = submit_file(root: sub_app_root, paths: path)
hsh = hsh.deep_merge read_yaml_erb(path: file, binding: binding) if file
end
@submit_config = hsh
end

# The OOD app object describing this app
def ood_app
@ood_app ||= OodApp.new(router)
end

# add a widget for choosing the cluster if one doesn't already exist
# and if users aren't defining they're own form.cluster and attributes.cluster
def add_cluster_widget(attributes, attribute_list)
return unless clusters.any?

attribute_list.prepend('cluster') unless attribute_list.include?('cluster')

attributes[:cluster] = if clusters.size > 1
{
widget: 'select',
label: 'Cluster',
options: clusters.map(&:id)
}
else
{
value: clusters.first.id.to_s,
fixed: true
}
end
end
end
end