Skip to content

Commit

Permalink
Merge pull request #18327 from branic/widgets_export_import
Browse files Browse the repository at this point in the history
Add support for exporting and importing widgets
  • Loading branch information
gtanzillo authored Jan 30, 2019
2 parents eb58c20 + 9478c4f commit 4b95808
Show file tree
Hide file tree
Showing 10 changed files with 869 additions and 0 deletions.
16 changes: 16 additions & 0 deletions lib/task_helpers/exports/widgets.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module TaskHelpers
class Exports
class Widgets
def export(options = {})
export_dir = options[:directory]

widgets = options[:all] ? MiqWidget.all : MiqWidget.where(:read_only => false)

widgets.each do |widget|
filename = Exports.safe_filename(widget.description, options[:keep_spaces])
File.write("#{export_dir}/#{filename}.yaml", MiqWidget.export_to_yaml([widget.id], MiqWidget))
end
end
end
end
end
26 changes: 26 additions & 0 deletions lib/task_helpers/imports/widgets.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module TaskHelpers
class Imports
class Widgets
def import(options = {})
return unless options[:source]

glob = File.file?(options[:source]) ? options[:source] : "#{options[:source]}/*.yaml"
Dir.glob(glob) do |filename|
$log.info("Importing Widgets from: #{filename}")

widget_options = { :userid => 'admin',
:overwrite => options[:overwrite],
:save => true }

begin
widget_fd = File.open(filename, 'r')
MiqWidget.import(widget_fd, widget_options)
rescue ActiveModel::UnknownAttributeError, RuntimeError => err
$log.error("Error importing #{filename} : #{err.message}")
warn("Error importing #{filename} : #{err.message}")
end
end
end
end
end
end
17 changes: 17 additions & 0 deletions lib/tasks/evm_export_import.rake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# * SmartState Analysis Scan Profiles
# * Customization Templates
# * Reports
# * Widgets

namespace :evm do
namespace :export do
Expand Down Expand Up @@ -105,6 +106,14 @@ namespace :evm do

exit # exit so that parameters to the first rake task are not run as rake tasks
end

desc 'Exports all widgets to individual YAML files'
task :widgets => :environment do
options = TaskHelpers::Exports.parse_options
TaskHelpers::Exports::Widgets.new.export(options)

exit # exit so that parameters to the first rake task are not run as rake tasks
end
end

namespace :import do
Expand Down Expand Up @@ -201,5 +210,13 @@ namespace :evm do

exit # exit so that parameters to the first rake task are not run as rake tasks
end

desc 'Imports all widgets from individual YAML files'
task :widgets => :environment do
options = TaskHelpers::Imports.parse_options
TaskHelpers::Imports::Widgets.new.import(options)

exit # exit so that parameters to the first rake task are not run as rake tasks
end
end
end
81 changes: 81 additions & 0 deletions spec/lib/task_helpers/exports/widgets_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
describe TaskHelpers::Exports::Widgets do
let(:export_dir) do
Dir.mktmpdir('miq_exp_dir')
end

before do
_guid, _server, _zone = EvmSpecHelper.create_guid_miq_server_zone

MiqReport.seed_report("Vendor and Guest OS")
MiqWidget.seed_widget("chart_vendor_and_guest_os")
MiqWidget.sync_from_hash(YAML.safe_load("
description: Test Widget
title: Test Widget
content_type: report
options:
:col_order:
- name
- vendor_display
:row_count: 5
visibility:
:roles:
- _ALL_
resource_name: Vendor and Guest OS
resource_type: MiqReport
enabled: true
read_only: false
", [Symbol], %i(col_order row_count roles)))
MiqWidget.sync_from_hash(YAML.safe_load("
description: Test Widget 2
title: Test Widget 2
content_type: report
options:
:col_order:
- name
- vendor_display
:row_count: 5
visibility:
:roles:
- _ALL_
resource_name: Vendor and Guest OS
resource_type: MiqReport
enabled: true
read_only: false
", [Symbol], %i(col_order row_count roles)))
end

after do
FileUtils.remove_entry export_dir
end

describe "when --all is not specified" do
let(:widget_filename1) { "#{export_dir}/Test_Widget.yaml" }
let(:widget_filename2) { "#{export_dir}/Test_Widget_2.yaml" }

it "exports custom widgets to individual files in a given directory" do
TaskHelpers::Exports::Widgets.new.export(:directory => export_dir)
expect(Dir[File.join(export_dir, '**', '*')].count { |file| File.file?(file) }).to eq(2)
widget1 = YAML.load_file(widget_filename1)
expect(widget1.first["MiqWidget"]["description"]).to eq("Test Widget")
widget2 = YAML.load_file(widget_filename2)
expect(widget2.first["MiqWidget"]["description"]).to eq("Test Widget 2")
end
end

describe "when --all is specified" do
let(:widget_filename1) { "#{export_dir}/Test_Widget.yaml" }
let(:widget_filename2) { "#{export_dir}/Test_Widget_2.yaml" }
let(:widget_filename3) { "#{export_dir}/chart_vendor_and_guest_os.yaml" }

it "exports all reports to individual files in a given directory" do
TaskHelpers::Exports::Widgets.new.export(:directory => export_dir, :all => true)
expect(Dir[File.join(export_dir, '**', '*')].count { |file| File.file?(file) }).to eq(3)
widget1 = YAML.load_file(widget_filename1)
expect(widget1.first["MiqWidget"]["description"]).to eq("Test Widget")
widget2 = YAML.load_file(widget_filename2)
expect(widget2.first["MiqWidget"]["description"]).to eq("Test Widget 2")
widget3 = YAML.load_file(widget_filename3)
expect(widget3.first["MiqWidget"]["description"]).to eq("chart_vendor_and_guest_os")
end
end
end
128 changes: 128 additions & 0 deletions spec/lib/task_helpers/imports/data/widgets/Test_Widget.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
- MiqWidget:
guid: d52ee383-6906-4312-bf48-b1bfaa4d8391
description: Test Widget
title: Test Widget
content_type: report
options:
:row_count: 10
:col_order:
- name
- power_state
- last_scan_on
visibility:
:roles:
- _ALL_
user_id:
resource_id: 81
resource_type: MiqReport
enabled: true
read_only: false
MiqReportContent:
- MiqReport:
title: Online VMs (Powered On)
rpt_group: Operations- Virtual Machines
rpt_type: Default
priority: 20
db: Vm
cols:
- v_datastore_path
- name
- power_state
- last_scan_on
include:
host:
columns:
- name
storage:
columns:
- name
col_order:
- host.name
- storage.name
- v_datastore_path
- name
- power_state
- last_scan_on
headers:
- Host
- Datastore
- Datastore Path
- VM Name
- Vm Power State
- Last Analysis Time
conditions: !ruby/object:MiqExpression
exp:
and:
- "=":
field: Vm-power_state
value: 'on'
- "=":
field: Vm-active
value: 'true'
order: Ascending
sortby:
- name
group:
graph:
dims:
filename: 400_Operations- Virtual Machines/020_Online VMs.yaml
file_mtime: !ruby/object:ActiveSupport::TimeWithZone
utc: &1 2018-04-27 20:10:20.000000000 Z
zone: !ruby/object:ActiveSupport::TimeZone
name: Etc/UTC
time: *1
categories:
timeline:
template_type: report
where_clause:
db_options:
generate_cols:
generate_rows:
col_formats:
tz:
time_profile_id:
display_filter:
col_options:
rpt_options:
miq_group_id:
user_id:
menu_name: Online VMs (Powered On)
MiqSchedule:
name: Test Widget
description: Test Widget
sched_action:
:method: generate_widget
filter: !ruby/object:MiqExpression
exp:
"=":
field: MiqWidget-id
value: 25
context_type:
col_details:
MiqWidget-id:
:data_type: :integer
:virtual_reflection: false
:virtual_column: false
:sql_support: true
:excluded_by_preprocess_options: false
:tag: false
:include: {}
:format_sub_type: :integer
pexp:
"=":
field: MiqWidget-id
value: 25
resource_type: MiqWidget
run_at:
:start_time: 2018-12-21 00:00:00.000000000 Z
:tz: UTC
:interval:
:unit: hourly
:value: 1
enabled: true
userid: system
prod_default: system
adhoc:
file_depot_id:
resource_id:
Loading

0 comments on commit 4b95808

Please sign in to comment.