diff --git a/app/models/git_repository.rb b/app/models/git_repository.rb index de3a494a771..f19b91c19bc 100644 --- a/app/models/git_repository.rb +++ b/app/models/git_repository.rb @@ -25,6 +25,29 @@ def self.delete_repo_dir(id, directory_name) FileUtils.rm_rf(directory_name) end + # Ping the git repository endpoint to verify that the network connection is still up. + # We use this approach for now over Rugged#check_connection because of a segfault: + # + # https://github.com/libgit2/rugged/issues/859 + # + def check_connection? + require 'net/ping/external' + + # URI library cannot handle git urls, so just convert it to a standard url. + temp_url = url.dup.to_s + temp_url = temp_url.sub(':', '/').sub('git@', 'https://') if temp_url.start_with?('git@') + + host = URI.parse(temp_url).hostname + + $log.debug("pinging '#{host}' to verify network connection") + ext_ping = Net::Ping::External.new(host) + + result = ext_ping.ping? + $log.debug("ping failed: #{ext_ping.exception}") unless result + + result + end + def refresh update_repo transaction do diff --git a/app/models/service_ansible_playbook.rb b/app/models/service_ansible_playbook.rb index 9bdc8a6206b..60f7264e396 100644 --- a/app/models/service_ansible_playbook.rb +++ b/app/models/service_ansible_playbook.rb @@ -2,7 +2,7 @@ class ServiceAnsiblePlaybook < ServiceGeneric include AnsibleExtraVarsMixin include AnsiblePlaybookMixin - delegate :playbook, :to => :service_template, :allow_nil => true + delegate :playbook, :repository, :to => :service_template, :allow_nil => true # A chance for taking options from automate script to override options from a service dialog def preprocess(action, add_options = {}) @@ -18,6 +18,10 @@ def execute(action) launch_ansible_job_queue(action) end + def check_connection(action) + repository(action).check_connection? + end + def launch_ansible_job_queue(action) task_opts = { :action => "Launching Ansible Job", diff --git a/app/models/service_template_ansible_playbook.rb b/app/models/service_template_ansible_playbook.rb index d09825ebc5e..919f97a35ba 100644 --- a/app/models/service_template_ansible_playbook.rb +++ b/app/models/service_template_ansible_playbook.rb @@ -76,6 +76,10 @@ def playbook(action) ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Playbook.find(config_info[action.downcase.to_sym][:playbook_id]) end + def repository(action) + GitRepository.find(config_info[action.downcase.to_sym][:repository_id]) + end + def update_catalog_item(options, auth_user = nil) config_info = validate_update_config_info(options) unless config_info diff --git a/spec/models/git_repository_spec.rb b/spec/models/git_repository_spec.rb index 961c09ae73a..0b7538f17f7 100644 --- a/spec/models/git_repository_spec.rb +++ b/spec/models/git_repository_spec.rb @@ -345,5 +345,49 @@ end end end + + context "check_connection?" do + require 'net/ping/external' + let(:ext_ping) { instance_double(Net::Ping::External) } + + before do + allow(Net::Ping::External).to receive(:new).and_return(ext_ping) + allow(ext_ping).to receive(:exception) + end + + it "returns true if it can ping the repo" do + allow(ext_ping).to receive(:ping?).and_return(true) + expect($log).to receive(:debug).with(/pinging '.*' to verify network connection/) + expect(repo.check_connection?).to eq(true) + end + + it "returns false if it cannot ping the repo" do + allow(ext_ping).to receive(:ping?).and_return(false) + expect($log).to receive(:debug).with(/pinging '.*' to verify network connection/) + expect($log).to receive(:debug).with(/ping failed: .*/) + expect(repo.check_connection?).to eq(false) + end + + it "handles git urls without issue" do + allow(repo).to receive(:url).and_return("git@example.com:ManageIQ/manageiq.git") + allow(ext_ping).to receive(:ping?).and_return(true) + expect($log).to receive(:debug).with(/pinging 'example.com' to verify network connection/) + expect(repo.check_connection?).to eq(true) + end + + it "handles ssh urls without issue" do + allow(repo).to receive(:url).and_return("ssh://user@example.com:443/manageiq.git") + allow(ext_ping).to receive(:ping?).and_return(true) + expect($log).to receive(:debug).with(/pinging 'example.com' to verify network connection/) + expect(repo.check_connection?).to eq(true) + end + + it "handles file urls without issue" do + allow(repo).to receive(:url).and_return("file://example.com/server/manageiq.git") + allow(ext_ping).to receive(:ping?).and_return(true) + expect($log).to receive(:debug).with(/pinging 'example.com' to verify network connection/) + expect(repo.check_connection?).to eq(true) + end + end end end