Skip to content

Commit

Permalink
Merge branch 'master' into save-fixed-attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
ashton22305 committed Sep 26, 2024
2 parents 4b2af25 + ab63139 commit b988ec6
Show file tree
Hide file tree
Showing 23 changed files with 1,729 additions and 105 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- data-hide attributes now respond to `false` setting in [3720](https://github.com/OSC/ondemand/pull/3720).
- auto_cores smart attribute has been added in [3727](https://github.com/OSC/ondemand/pull/3727).
- Batch connect apps now respond to form_header to display a header in [3763](https://github.com/OSC/ondemand/pull/3763).
- auto_clusters now set maximums for auto_cores in [3778](https://github.com/OSC/ondemand/pull/3778).

### Changed
- Script models have been renamed to Launcher in [3397](https://github.com/OSC/ondemand/pull/3397).
Expand All @@ -50,6 +51,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Esbuild now has a plugin for to use source code for minified dependencies in [3693](https://github.com/OSC/ondemand/pull/3693).
- Remote file uploads now move the tempfile asychronously in [3739](https://github.com/OSC/ondemand/pull/3739).
- Modals no longer pop up for some errors in the files app in [3769](https://github.com/OSC/ondemand/pull/3769).
- The shell app now has configurations for ping ponging. Ping pongs are disabled by default, will only ping pong
for a certain duration after inactivity and the connections will close altogether after a certian duration regardless
of activity in [3805](https://github.com/OSC/ondemand/pull/3805) and [3810](https://github.com/OSC/ondemand/pull/3810).

### Fixed
- Ensure that the asset directory is clean when building in [3356](https://github.com/OSC/ondemand/pull/3356).
Expand All @@ -66,6 +70,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
and [3776](https://github.com/OSC/ondemand/pull/3776).
- ood_auth_map now accounts for more than just \w for usernames in [3753](https://github.com/OSC/ondemand/pull/3753).
- Pipes and fifos no longer show as downloadable in [3718](https://github.com/OSC/ondemand/pull/3718).
- Allowlist compuations have been optimized in [3804](https://github.com/OSC/ondemand/pull/3804).

### Security

Expand Down
94 changes: 49 additions & 45 deletions apps/dashboard/app/controllers/batch_connect/settings_controller.rb
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@
# frozen_string_literal: true

# The controller to manage BatchConnect saved settings
class BatchConnect::SettingsController < ApplicationController
include BatchConnectConcern
include UserSettingStore

# GET /batch_connect/<app_token>/settings/<settings_name>
def show
set_app_groups
set_saved_settings

request_params = settings_request_params
app_token = request_params[:token]
settings_name = request_params[:id]
settings_values = bc_templates(app_token)[settings_name.to_sym]
if settings_values.nil?
redirect_to new_batch_connect_session_context_path(token: app_token),
alert: t('dashboard.bc_saved_settings.missing_settings')
return
module BatchConnect
class SettingsController < ApplicationController
include BatchConnectConcern
include UserSettingStore

# GET /batch_connect/<app_token>/settings/<settings_name>
def show
set_app_groups
set_saved_settings

request_params = settings_request_params
app_token = request_params[:token]
settings_name = request_params[:id]
settings_values = bc_templates(app_token)[settings_name.to_sym]
if settings_values.nil?
redirect_to new_batch_connect_session_context_path(token: app_token),
alert: t('dashboard.bc_saved_settings.missing_settings')
return
end

@settings = BatchConnect::Settings.new(app_token, settings_name, settings_values)
if @settings.outdated?
flash.now[:alert] = t('dashboard.bc_saved_settings.outdated_message', app_title: @settings.app.title)
end
end

@settings = BatchConnect::Settings.new(app_token, settings_name, settings_values)
if @settings.outdated?
flash.now[:alert] = t('dashboard.bc_saved_settings.outdated_message', app_title: @settings.app.title)
# DELETE /batch_connect/<app_token>/settings/<settings_name>
def destroy
request_params = settings_request_params
app_token = request_params[:token]
settings_name = request_params[:id]
delete_bc_template(app_token, settings_name)
redirect_to new_batch_connect_session_context_path(token: app_token),
notice: t('dashboard.bc_saved_settings.deleted_message', settings_name: settings_name)
end
end

# DELETE /batch_connect/<app_token>/settings/<settings_name>
def destroy
request_params = settings_request_params
app_token = request_params[:token]
settings_name = request_params[:id]
delete_bc_template(app_token, settings_name)
redirect_to new_batch_connect_session_context_path(token: app_token),
notice: t('dashboard.bc_saved_settings.deleted_message', settings_name: settings_name)
end

private
private

def settings_request_params
params.permit(:token, :id)
end
def settings_request_params
params.permit(:token, :id)
end

# Set the all the saved settings to render the navigation
def set_saved_settings
@bc_saved_settings = all_bc_templates
end
# Set the all the saved settings to render the navigation
def set_saved_settings
@bc_saved_settings = all_bc_templates
end

# Set list of app lists for navigation
def set_app_groups
@sys_app_groups = bc_sys_app_groups
@usr_app_groups = bc_usr_app_groups
@dev_app_groups = bc_dev_app_groups
@apps_menu_group = bc_custom_apps_group
# Set list of app lists for navigation
def set_app_groups
@sys_app_groups = bc_sys_app_groups
@usr_app_groups = bc_usr_app_groups
@dev_app_groups = bc_dev_app_groups
@apps_menu_group = bc_custom_apps_group
end
end
end
2 changes: 1 addition & 1 deletion apps/dashboard/app/controllers/files_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def upload

@transfer = @path.handle_upload(params[:file].tempfile)
if @transfer
render "transfers/show"
render 'transfers/show'
else
render json: {}
end
Expand Down
1 change: 1 addition & 0 deletions apps/dashboard/app/javascript/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ function moveCompletedPanel(id, newHTML) {

const div = document.createElement('div');
div.id = id;
div.classList.add('col-md-4');

const row = document.getElementById('completed_jobs');
row.appendChild(div);
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/app/javascript/script_show.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { makeChangeHandlers } from './dynamic_forms';

jQuery(function() {
makeChangeHandlers('script');
makeChangeHandlers('launcher');
});
50 changes: 50 additions & 0 deletions apps/dashboard/app/lib/cluster_cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module ClusterCache
def cluster_options
Rails.cache.fetch('script_cluster_options', expires_in: 4.hours) do
max_cores_map = cluster_max_cores
batch_clusters.map do |cluster|
options = if max_cores_map[cluster.id]
{ 'data-max-auto-cores': max_cores_map[cluster.id] }
else
{}
end
[cluster.id.to_s, cluster.id.to_s, options]
end.sort_by { |option| option[0] }
end
end

def cluster_nodes
Rails.cache.fetch('script_cluster_nodes', expires_in: 4.hours) do
{}.tap do |hash|
batch_clusters.map do |cluster|
hash[cluster.id] = cluster.job_adapter.nodes if cluster.slurm?
end
end
end
end

def cluster_max_cores
Rails.cache.fetch('script_cluster_max_values', exipres_in: 4.hours) do
{}.tap do |hash|
cluster_nodes.each do |cluster_id, nodes|
max_node = nodes.max { |a, b| a.procs <=> b.procs }
hash[cluster_id] = max_node.procs if max_node
end
end
end
end

def batch_clusters
Rails.cache.fetch('script_batch_clusters', expires_in: 4.hours) do
Configuration.job_clusters.reject do |c|
reject_cluster?(c)
end
end
end

def reject_cluster?(cluster)
cluster.kubernetes? || cluster.linux_host? || cluster.systemd?
end
end
2 changes: 2 additions & 0 deletions apps/dashboard/app/lib/smart_attributes/attribute_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ def build(id, opts = {})
if respond_to?(build_method)
send(build_method, opts)
else
# date_field will throw an error if the value is an empty string.
opts[:value] = Date.today if opts[:widget] == 'date_field' && opts[:value].to_s.empty?
Attribute.new(id, opts)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,20 @@

module SmartAttributes
class AttributeFactory

extend ClusterCache
# Build this attribute object. Must specify a valid directory in opts
#
# @param opts [Hash] attribute's options
# @return [Attributes::AutoBatchClusters] the attribute object
def self.build_auto_batch_clusters(opts = {})
options = batch_clusters
options = cluster_options

static_opts = {
options: options
}.merge(opts.without(:options).to_h)

Attributes::AutoBatchClusters.new('auto_batch_clusters', static_opts)
end

def self.batch_clusters
Rails.cache.fetch('script_batch_clusters', expires_in: 4.hours) do
Configuration.job_clusters.reject do |c|
reject_cluster?(c)
end.map(&:id).map(&:to_s).sort
end
end

def self.reject_cluster?(cluster)
cluster.kubernetes? || cluster.linux_host? || cluster.systemd?
end
end

module Attributes
Expand All @@ -37,7 +25,7 @@ class AutoBatchClusters < Attribute
# Defaults to first cluster in the options
# @return [String] attribute value
def value
(opts[:value] || opts[:options].first).to_s
(opts[:value] || opts[:options].first.first).to_s
end

def widget
Expand Down
19 changes: 9 additions & 10 deletions apps/dashboard/app/models/allowlist_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ def initialize(allowlist)
# @raises ArgumentError if any allowlist path or permitted? argument
# has the form ~user/some/path where user doesn't exist
def permitted?(path)
return true if allowlist.blank?
real_path = real_expanded_path(path.to_s)
key = path_to_key(real_path)
Rails.cache.fetch(key) do
allowlist.blank? || allowlist.any? { |parent| child?(Pathname.new(parent), real_path) }
allowlist.any? { |parent| child?(Pathname.new(parent), real_path) }
end
end

Expand Down Expand Up @@ -71,19 +72,17 @@ def real_expanded_path_not_exist(path)
Pathname.new(path).expand_path
end

# Determine if child is a subpath of parent
#
# If the relative path from the child to the supposed parent includes '..'
# then child is not a subpath of parent
# Determine if child is a subpath of parent.
# This does not access the filesystem, so symlinks should be evaluated before this.
#
# @param parent [Pathname]
# @param child [Pathname]
# @return Boolean
def child?(parent, child)
!child.expand_path.relative_path_from(
parent.expand_path
).each_filename.to_a.include?(
'..'
)
# Expand both paths to evaluate any potential ".." components to be able to compare them as strings.
p = parent.expand_path.to_s
c = child.expand_path.to_s
# Child path if it is same as parent path, or has additional components after "/".
c.start_with?(p) && (c.size == p.size || c[p.size] == "/")
end
end
3 changes: 2 additions & 1 deletion apps/dashboard/app/views/projects/_job_details.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<div id="<%= id %>" data-job-poller="true"
data-job-cluster="<%= job.cluster %>"
data-job-id="<%= job.id %>"
data-job-status="<%= job.status.to_s %>">
data-job-status="<%= job.status.to_s %>"
class="col-md-4">

<div class="d-flex justify-content-center">
<div class="spinner-border" role="status">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<%= job.id %> <%= status_text(job.status.to_s) %>
</span>
</button>
<div class="collapse col-md-4" id="<%= id %>_data">
<div class="collapse" id="<%= id %>_data">
<div class="card card-body">
<table class="table table-bordered table-sm m-0 mb-2">
<% job.to_human_display.each do |name, value| %>
Expand Down
8 changes: 6 additions & 2 deletions apps/dashboard/app/views/projects/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@

<div class="row">
<h2 class="h3 d-flex justify-content-center">Completed Jobs</h2>
<div id="completed_jobs">
<%= render(partial: 'job_details_content', collection: @project.completed_jobs, as: :job) %>
<div id="completed_jobs" class="row">
<%- @project.completed_jobs.each do |job| -%>
<div class="col-md-4" id="<%= "job_#{job.cluster}_#{job.id}" %>">
<%= render(partial: 'job_details_content', locals: { job: job }) %>
</div>
<%- end -%>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit b988ec6

Please sign in to comment.