Skip to content

Commit

Permalink
anonymous ftp upload option
Browse files Browse the repository at this point in the history
https://bugzilla.redhat.com/show_bug.cgi?id=1535345
https://bugzilla.redhat.com/show_bug.cgi?id=1632433

This will allow customers to upload files to support sites

To add this option, add to `en.yml`:

```yml
  database_admin:
    menu_order:
    - local
    - ftp://ftp.example.com/incoming/999999-db.backup
    local: Local file
    prompts:
      ftp.example.com:
        filename_text: "The case number dash (-) filename. (e.g.: 12345-db.backup)"
        filename_validator: "^[0-9]{4,}-..*"
```
  • Loading branch information
kbrock committed Sep 28, 2018
1 parent 688f94a commit 24842e7
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 3 deletions.
42 changes: 39 additions & 3 deletions lib/manageiq/appliance_console/database_admin.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'manageiq/appliance_console/errors'
require 'uri'

module ManageIQ
module ApplianceConsole
Expand Down Expand Up @@ -57,8 +58,12 @@ def ask_file_location
@backup_type = ask_with_menu(*file_menu_args) do |menu|
menu.choice(CANCEL) { |_| raise MiqSignalError }
end
# calling methods like ask_ftp_file_options and ask_s3_file_options
send("ask_#{backup_type}_file_options")
if URI(backup_type).scheme
ask_custom_file_options(backup_type)
else
# calling methods like ask_ftp_file_options and ask_s3_file_options
send("ask_#{backup_type}_file_options")
end
end

def ask_local_file_options
Expand Down Expand Up @@ -134,6 +139,20 @@ def ask_ftp_file_options
@task_params = ["--", params]
end

def ask_custom_file_options(server_uri)
@filename = just_ask(*filename_prompt_args) unless action == :restore
sample_case = server_uri.split("/").last
hostname = URI(server_uri).host
uri_filename = ask_custom_prompt(hostname, 'filename', "Target filename (e.g.: #{sample_case})")
@uri = server_uri.gsub(sample_case, uri_filename)

params = { :uri => uri }
params[:remote_file_name] = filename if filename

@task = "evm:db:#{action}:remote"
@task_params = ["--", params]
end

def ask_to_delete_backup_after_restore
if action == :restore && backup_type == LOCAL_FILE
say("The local database restore file is located at: '#{uri}'.\n")
Expand Down Expand Up @@ -177,13 +196,20 @@ def confirm_and_execute

def allowed_to_execute?
return true unless action == :restore

say("\nNote: A database restore cannot be undone. The restore will use the file: #{uri}.\n")
agree("Are you sure you would like to restore the database? (Y/N): ")
end

def file_options
@file_options ||= I18n.t("database_admin.menu_order").each_with_object({}) do |file_option, h|
h[I18n.t("database_admin.#{file_option}")] = file_option
# special anonymous ftp sites are defined by uri
uri = URI(file_option)
if uri.scheme
h["#{uri.scheme} to #{uri.host}"] = file_option
else
h[I18n.t("database_admin.#{file_option}")] = file_option
end
end
end

Expand All @@ -202,6 +228,16 @@ def setting_header

private

def ask_custom_prompt(type, prompt_name, default_prompt)
# type (domain name) has a period in it, so we need to look it up by [] instead of the traditional i18n method
prompts = I18n.t("database_admin.prompts", default: nil)
prompts = prompts && prompts[type.to_sym]
prompt_text = prompts && prompts["#{prompt_name}_text".to_sym] || default_prompt
prompt_regex = prompts && prompts["#{prompt_name}_validator".to_sym]
validator = prompt_regex ? ->(x) { x.to_s =~ /#{prompt_regex}/ } : ->(x) { x.to_s.present? }
just_ask(prompt_text, nil, validator)
end

def should_exclude_tables?
ask_yn?("Would you like to exclude tables in the dump") do |q|
q.readline = true
Expand Down
101 changes: 101 additions & 0 deletions spec/database_admin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,25 @@ def confirm_and_execute
say "6"
expect { subject.ask_file_location }.to raise_error signal_error
end

context "with localized file upload" do
it "displays anonymous ftp option" do
expect(I18n).to receive(:t).with("database_admin.menu_order").and_return(%w(local ftp://example.com/inbox/filename.txt))
expect(I18n).to receive(:t).with("database_admin.local").and_return("The Local file")
expect(subject).to receive(:ask_local_file_options).once
say ""
subject.ask_file_location
expect_output <<-PROMPT.strip_heredoc.chomp + " "
Dump Output File Name
1) The Local file
2) ftp to example.com
3) Cancel
Choose the dump output file name: |1|
PROMPT
end
end
end

describe "#ask_local_file_options" do
Expand Down Expand Up @@ -1716,6 +1735,88 @@ def confirm_and_execute
end
end

describe "#ask_custom_file_options" do
let(:example_uri) { "ftp://example.com/inbox/sample.txt" }
let(:uri) { "ftp://example.com/inbox/sample.txt".gsub("sample.txt", target) }
let(:host) { URI(example_uri).host }
let(:filename) { "/tmp/localfile.txt" }
let(:target) { "123456-filename.txt" }
let(:uri_prompt) { "Enter the location to save the remote backup file to\nExample: #{example_uri}" }
let(:user_prompt) { "Enter the username with access to this file.\nExample: 'mydomain.com/user'" }
let(:pass_prompt) { "Enter the password for #{user}" }
let(:errmsg) { "a valid URI" }

let(:expected_task_params) do
[
"--",
{
:uri => uri,
:remote_file_name => filename
}
]
end

context "with a valid target" do
before do
say [filename, target]
expect(subject.ask_custom_file_options(example_uri)).to be_truthy
end

it "sets @uri to point to the ftp share url" do
expect(subject.uri).to eq(uri)
end

it "sets @filename to nil" do
expect(subject.filename).to eq(filename)
end

it "sets @task to point to 'evm:db:dump:remote'" do
expect(subject.task).to eq("evm:db:dump:remote")
end

it "sets @task_params to point to the ftp file" do
expect(subject.task_params).to eq(expected_task_params)
end
end

context "with invalid target (then valid)" do
before do
say [filename, "", target]
expect(subject.ask_custom_file_options(example_uri)).to be_truthy
end

it "sets @task_params to point to the ftp file" do
expect(subject.task_params).to eq(expected_task_params)
end
end

context "with custom prompts" do
before do
expect(I18n).to receive(:t).with("database_admin.prompts").and_return(
host.to_sym => {
:filename_text => "Target please",
:filename_validator => "^[0-9]+-.+$"
}
)

# if it doesn't ask again, it won't get the right task_params
say [filename, "", "bad-2", target]
expect(subject.ask_custom_file_options(example_uri)).to be_truthy
expect_readline_question_asked "Enter the location to save the dump file to: |/tmp/evm_db.dump|"
expect_readline_question_asked "Target please: "
expect_output [
"Please provide in the specified format",
"? Please provide in the specified format",
"? ",
].join("\n")
end

it "uses custom validation" do
expect(subject.task_params).to eq(expected_task_params)
end
end
end

describe "#ask_to_delete_backup_after_restore" do
context "when @backup_type is LOCAL_FILE" do
let(:uri) { described_class::DB_RESTORE_FILE }
Expand Down

0 comments on commit 24842e7

Please sign in to comment.