{"action":"created","comment":{"url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/comments/190979103","pull_request_review_id":123471861,"id":190979103,"diff_hunk":"@@ -18,294 +18,705 @@\n     end\n   end\n \n-  describe \"#ask_questions\" do\n-    it \"asks for file location, asks to delete backup, runs restore\" do\n-      expect(subject).to receive(:say).with(\"Restore Database From Backup\\n\\n\")\n-      expect(subject).to receive(:ask_file_location)\n+  context \"for DB restore\" do\n+    subject { described_class.new(:restore, input, output) }\n \n-      subject.ask_questions\n-    end\n-  end\n+    describe \"#ask_questions\" do\n+      it \"asks for file location, asks to delete backup, runs restore\" do\n+        expect(subject).to receive(:say).with(\"Restore Database From Backup\\n\\n\")\n+        expect(subject).to receive(:ask_file_location)\n \n-  describe \"#activate\" do\n-    it \"asks for file location, asks to delete backup, runs restore\" do\n-      expect(subject).to receive(:clear_screen)\n-      expect(subject).to receive(:say).with(\"Restore Database From Backup\\n\\n\")\n-      expect(subject).to receive(:ask_to_delete_backup_after_restore)\n-      expect(subject).to receive(:confirm_and_execute)\n-\n-      subject.activate\n+        subject.ask_questions\n+      end\n     end\n-  end\n \n-  describe \"#ask_file_location\" do\n-    it \"displays the menu\" do\n-      expect(subject).to receive(:ask_local_file_options).once\n-      say \"\"\n-      subject.ask_file_location\n-      expect_output <<-PROMPT.strip_heredoc.chomp + \" \"\n-        Restore Database File\n-\n-        1) Local file\n-        2) Network File System (NFS)\n-        3) Samba (SMB)\n-        4) Cancel\n-\n-        Choose the restore database file: |1|\n-      PROMPT\n-    end\n+    describe \"#activate\" do\n+      it \"asks for file location, asks to delete backup, runs restore\" do\n+        expect(subject).to receive(:clear_screen)\n+        expect(subject).to receive(:say).with(\"Restore Database From Backup\\n\\n\")\n+        expect(subject).to receive(:ask_to_delete_backup_after_restore)\n+        expect(subject).to receive(:confirm_and_execute)\n \n-    it \"defaults to local file\" do\n-      expect(subject).to receive(:ask_local_file_options).once\n-      say \"\"\n-      subject.ask_file_location\n-      expect(subject.backup_type).to eq(described_class::LOCAL_FILE)\n+        subject.activate\n+      end\n     end\n \n-    it \"calls #ask_local_file_options when choosen\" do\n-      expect(subject).to receive(:ask_local_file_options).once\n-      say \"1\"\n-      subject.ask_file_location\n-      expect(subject.backup_type).to eq(described_class::LOCAL_FILE)\n-    end\n+    describe \"#ask_file_location\" do\n+      it \"displays the menu\" do\n+        expect(subject).to receive(:ask_local_file_options).once\n+        say \"\"\n+        subject.ask_file_location\n+        expect_output <<-PROMPT.strip_heredoc.chomp + \" \"\n+          Restore Database File\n \n-    it \"calls #ask_nfs_file_options when choosen\" do\n-      expect(subject).to receive(:ask_nfs_file_options).once\n-      say \"2\"\n-      subject.ask_file_location\n-      expect(subject.backup_type).to eq(described_class::NFS_FILE)\n-    end\n+          1) Local file\n+          2) Network File System (NFS)\n+          3) Samba (SMB)\n+          4) Cancel\n \n-    it \"calls #ask_smb_file_options when choosen\" do\n-      expect(subject).to receive(:ask_smb_file_options).once\n-      say \"3\"\n-      subject.ask_file_location\n-      expect(subject.backup_type).to eq(described_class::SMB_FILE)\n-    end\n+          Choose the restore database file: |1|\n+        PROMPT\n+      end\n \n-    it \"cancels when CANCEL option is choosen\" do\n-      say \"4\"\n-      expect { subject.ask_file_location }.to raise_error signal_error\n-    end\n-  end\n+      it \"defaults to local file\" do\n+        expect(subject).to receive(:ask_local_file_options).once\n+        say \"\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::LOCAL_FILE)\n+      end\n \n-  describe \"#ask_local_file_options\" do\n-    let(:file)      { Tempfile.new(\"foo.backup\").tap(&:close) }\n-    let(:prmpt)     { \"location of the local restore file\" }\n-    let(:default)   { described_class::DB_RESTORE_FILE }\n-    let(:errmsg)    { \"file that exists\" }\n+      it \"calls #ask_local_file_options when choosen\" do\n+        expect(subject).to receive(:ask_local_file_options).once\n+        say \"1\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::LOCAL_FILE)\n+      end\n \n-    context \"with no filename given\" do\n-      before do\n-        # stub validator for default answer, since it probably doesn't exist on\n-        # the machine running these tests.\n-        stub_const(\"#{described_class.name}::LOCAL_FILE_VALIDATOR\", ->(_) { true })\n+      it \"calls #ask_nfs_file_options when choosen\" do\n+        expect(subject).to receive(:ask_nfs_file_options).once\n+        say \"2\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::NFS_FILE)\n+      end\n \n-        say \"\"\n-        subject.ask_local_file_options\n+      it \"calls #ask_smb_file_options when choosen\" do\n+        expect(subject).to receive(:ask_smb_file_options).once\n+        say \"3\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::SMB_FILE)\n       end\n \n-      it \"sets @uri to the default filename\" do\n-        expect(subject.uri).to eq(default)\n+      it \"cancels when CANCEL option is choosen\" do\n+        say \"4\"\n+        expect { subject.ask_file_location }.to raise_error signal_error\n       end\n     end\n \n-    context \"with a valid filename given\" do\n-      before do\n-        say file.path.to_s\n-        subject.ask_local_file_options\n-      end\n+    describe \"#ask_local_file_options\" do\n+      let(:file)      { Tempfile.new(\"foo.backup\").tap(&:close) }\n+      let(:prmpt)     { \"location of the local restore file\" }\n+      let(:default)   { described_class::DB_RESTORE_FILE }\n+      let(:errmsg)    { \"file that exists\" }\n \n-      it \"sets @uri to point to the local file\" do\n-        expect(subject.uri).to eq(file.path)\n+      context \"with no filename given\" do\n+        before do\n+          # stub validator for default answer, since it probably doesn't exist on\n+          # the machine running these tests.\n+          stub_const(\"#{described_class.name}::LOCAL_FILE_VALIDATOR\", ->(_) { true })\n+\n+          say \"\"\n+          subject.ask_local_file_options\n+        end\n+\n+        it \"sets @uri to the default filename\" do\n+          expect(subject.uri).to eq(default)\n+        end\n       end\n \n-      it \"sets @task to point to 'evm:db:restore:local'\" do\n-        expect(subject.task).to eq(\"evm:db:restore:local\")\n+      context \"with a valid filename given\" do\n+        before do\n+          say file.path.to_s\n+          subject.ask_local_file_options\n+        end\n+\n+        it \"sets @uri to point to the local file\" do\n+          expect(subject.uri).to eq(file.path)\n+        end\n+\n+        it \"sets @task to point to 'evm:db:restore:local'\" do\n+          expect(subject.task).to eq(\"evm:db:restore:local\")\n+        end\n+\n+        it \"sets @task_params to point to the local file\" do\n+          expect(subject.task_params).to eq([\"--\", {:local_file => file.path}])\n+        end\n       end\n \n-      it \"sets @task_params to point to the local file\" do\n-        expect(subject.task_params).to eq([\"--\", {:local_file => file.path}])\n+      context \"with an invalid filename given\" do\n+        let(:bad_filename) { \"#{file.path}.bad_mmkay\" }\n+\n+        before do\n+          say [bad_filename, file.path.to_s]\n+          subject.ask_local_file_options\n+        end\n+\n+        it \"reprompts the user and then properly sets the options\" do\n+          error = \"Please provide #{errmsg}\"\n+          expect_heard [\"Enter the #{prmpt}: \", error, prompt]\n+\n+          expect(subject.uri).to         eq(file.path)\n+          expect(subject.task).to        eq(\"evm:db:restore:local\")\n+          expect(subject.task_params).to eq([\"--\", {:local_file => file.path}])\n+        end\n       end\n     end\n \n-    context \"with an invalid filename given\" do\n-      let(:bad_filename) { \"#{file.path}.bad_mmkay\" }\n+    describe \"#ask_nfs_file_options\" do\n+      let(:example_uri) { subject.sample_url('nfs') }\n+      let(:prmpt)       { \"location of the remote backup file\\nExample: #{example_uri}\" }\n+      let(:errmsg)      { \"a valid URI\" }\n \n-      before do\n-        say [bad_filename, file.path.to_s]\n-        subject.ask_local_file_options\n-      end\n+      context \"with a valid uri given\" do\n+        before do\n+          say example_uri\n+          subject.ask_nfs_file_options\n+        end\n+\n+        it \"sets @uri to point to the nfs file\" do\n+          expect(subject.uri).to eq(example_uri)\n+        end\n \n-      it \"reprompts the user and then properly sets the options\" do\n-        error = \"Please provide #{errmsg}\"\n-        expect_heard [\"Enter the #{prmpt}: \", error, prompt]\n+        it \"sets @task to point to 'evm:db:restore:remote'\" do\n+          expect(subject.task).to eq(\"evm:db:restore:remote\")\n+        end\n \n-        expect(subject.uri).to         eq(file.path)\n-        expect(subject.task).to        eq(\"evm:db:restore:local\")\n-        expect(subject.task_params).to eq([\"--\", {:local_file => file.path}])\n+        it \"sets @task_params to point to the nfs file\" do\n+          expect(subject.task_params).to eq([\"--\", {:uri => example_uri}])\n+        end\n       end\n-    end\n-  end\n \n-  describe \"#ask_nfs_file_options\" do\n-    let(:example_uri) { subject.sample_url('nfs') }\n-    let(:prmpt)       { \"location of the remote backup file\\nExample: #{example_uri}\" }\n-    let(:errmsg)      { \"a valid URI\" }\n+      context \"with an invalid uri given\" do\n+        let(:bad_uri) { \"file://host.mydomain.com/path/to/file\" }\n \n-    context \"with a valid uri given\" do\n-      before do\n-        say example_uri\n-        subject.ask_nfs_file_options\n+        before do\n+          say [bad_uri, example_uri]\n+          subject.ask_nfs_file_options\n+        end\n+\n+        it \"reprompts the user and then properly sets the options\" do\n+          error = \"Please provide #{errmsg}\"\n+          expect_heard [\"Enter the #{prmpt}: \", error, prompt]\n+\n+          expect(subject.uri).to         eq(example_uri)\n+          expect(subject.task).to        eq(\"evm:db:restore:remote\")\n+          expect(subject.task_params).to eq([\"--\", {:uri => example_uri}])\n+        end\n       end\n+    end\n \n-      it \"sets @uri to point to the nfs file\" do\n-        expect(subject.uri).to eq(example_uri)\n+    describe \"#ask_smb_file_options\" do\n+      let(:example_uri) { subject.sample_url('smb') }\n+      let(:user)        { 'example.com/admin' }\n+      let(:pass)        { 'supersecret' }\n+      let(:uri_prompt)  { \"Enter the location of the remote backup file\\nExample: #{example_uri}\" }\n+      let(:user_prompt) { \"Enter the username with access to this file.\\nExample: 'mydomain.com/user'\" }\n+      let(:pass_prompt) { \"Enter the password for #{user}\" }\n+      let(:errmsg)      { \"a valid URI\" }\n+\n+      let(:expected_task_params) do\n+        [\n+          \"--\",\n+          {\n+            :uri          => example_uri,\n+            :uri_username => user,\n+            :uri_password => pass\n+          }\n+        ]\n       end\n \n-      it \"sets @task to point to 'evm:db:restore:remote'\" do\n-        expect(subject.task).to eq(\"evm:db:restore:remote\")\n+      context \"with a valid uri, username, and password given\" do\n+        before do\n+          say [example_uri, user, pass]\n+          subject.ask_smb_file_options\n+        end\n+\n+        it \"sets @uri to point to the smb file\" do\n+          expect(subject.uri).to eq(example_uri)\n+        end\n+\n+        it \"sets @task to point to 'evm:db:restore:local'\" do\n+          expect(subject.task).to eq(\"evm:db:restore:remote\")\n+        end\n+\n+        it \"sets @task_params to point to the smb file, username, and password\" do\n+          expect(subject.task_params).to eq(expected_task_params)\n+        end\n       end\n \n-      it \"sets @task_params to point to the nfs file\" do\n-        expect(subject.task_params).to eq([\"--\", {:uri => example_uri}])\n+      context \"with a invalid uri given\" do\n+        let(:bad_uri) { \"nfs://host.mydomain.com/path/to/file\" }\n+\n+        before do\n+          say [bad_uri, example_uri, user, pass]\n+          subject.ask_smb_file_options\n+        end\n+\n+        it \"reprompts the user and then properly sets the options\" do\n+          error = \"Please provide #{errmsg}\"\n+\n+          expect_readline_question_asked uri_prompt\n+          expect_readline_question_asked user_prompt\n+          expect_heard [\n+            uri_prompt,\n+            error,\n+            prompt,\n+            \"#{pass_prompt}: ***********\\n\"\n+          ]\n+\n+          expect(subject.uri).to         eq(example_uri)\n+          expect(subject.task).to        eq(\"evm:db:restore:remote\")\n+          expect(subject.task_params).to eq(expected_task_params)\n+        end\n       end\n     end\n \n-    context \"with an invalid uri given\" do\n-      let(:bad_uri) { \"file://host.mydomain.com/path/to/file\" }\n+    describe \"#ask_to_delete_backup_after_restore\" do\n+      context \"when @backup_type is LOCAL_FILE\" do\n+        let(:uri) { described_class::DB_RESTORE_FILE }\n \n-      before do\n-        say [bad_uri, example_uri]\n-        subject.ask_nfs_file_options\n+        before do\n+          subject.instance_variable_set(:@uri, uri)\n+          subject.instance_variable_set(:@backup_type, described_class::LOCAL_FILE)\n+        end\n+\n+        it \"sets @delete_agree if the user agrees\" do\n+          say \"y\"\n+          subject.ask_to_delete_backup_after_restore\n+          expect_output <<-PROMPT.strip_heredoc.chomp + \" \"\n+            The local database restore file is located at: '#{uri}'.\n+            Should this file be deleted after completing the restore? (Y/N):\n+          PROMPT\n+        end\n+\n+        it \"sets @delete_agree to true if the user agrees\" do\n+          say \"y\"\n+          subject.ask_to_delete_backup_after_restore\n+          expect(subject.delete_agree).to eq(true)\n+        end\n+\n+        it \"sets @delete_agree to false if the user disagrees\" do\n+          say \"n\"\n+          subject.ask_to_delete_backup_after_restore\n+          expect(subject.delete_agree).to eq(false)\n+        end\n       end\n \n-      it \"reprompts the user and then properly sets the options\" do\n-        error = \"Please provide #{errmsg}\"\n-        expect_heard [\"Enter the #{prmpt}: \", error, prompt]\n+      context \"when @backup_type not is LOCAL_FILE\" do\n+        let(:uri) { described_class::DB_RESTORE_FILE }\n \n-        expect(subject.uri).to         eq(example_uri)\n-        expect(subject.task).to        eq(\"evm:db:restore:remote\")\n-        expect(subject.task_params).to eq([\"--\", {:uri => example_uri}])\n+        before do\n+          subject.instance_variable_set(:@uri, uri)\n+          subject.instance_variable_set(:@backup_type, described_class::NFS_FILE)\n+        end\n+\n+        it \"no-ops\" do\n+          subject.ask_to_delete_backup_after_restore\n+          expect_output \"\"\n+        end\n+      end\n+\n+      describe \"#confirm_and_execute\" do\n+        let(:uri)             { \"/tmp/my_db.backup\" }\n+        let(:agree)           { \"y\" }\n+        let(:task)            { \"evm:db:restore:local\" }\n+        let(:task_params)     { [\"--\", { :uri => uri }] }\n+        let(:utils)           { ManageIQ::ApplianceConsole::Utilities }\n+\n+        before do\n+          subject.instance_variable_set(:@uri, uri)\n+          subject.instance_variable_set(:@delete_agree, true)\n+          expect(STDIN).to receive(:getc)\n+          allow(File).to receive(:delete)\n+        end\n+\n+        def confirm_and_execute\n+          say agree\n+          subject.confirm_and_execute\n+        end\n+\n+        context \"when it is successful\" do\n+          before { expect(utils).to receive(:rake).and_return(true) }\n+\n+          it \"deletes the backup file\" do\n+            expect(File).to receive(:delete).with(uri).once\n+            confirm_and_execute\n+          end\n+\n+          it \"outputs waits for user to press a key to continue\" do\n+            confirm_and_execute\n+            expect_output <<-PROMPT.strip_heredoc\n+\n+              Note: A database restore cannot be undone.  The restore will use the file: #{uri}.\n+              Are you sure you would like to restore the database? (Y/N): \n+              Restoring the database...\n+\n+              Removing the database restore file #{uri}...\n+\n+              Press any key to continue.\n+            PROMPT\n+          end\n+\n+          context \"without a delete agreement\" do\n+            before do\n+              subject.instance_variable_set(:@delete_agree, false)\n+            end\n+\n+            it \"does not delete the backup file\" do\n+              expect(File).to receive(:delete).with(uri).never\n+              confirm_and_execute\n+            end\n+\n+            it \"outputs waits for user to press a key to continue\" do\n+              confirm_and_execute\n+              expect_output <<-PROMPT.strip_heredoc\n+\n+                Note: A database restore cannot be undone.  The restore will use the file: #{uri}.\n+                Are you sure you would like to restore the database? (Y/N): \n+                Restoring the database...\n+\n+                Press any key to continue.\n+              PROMPT\n+            end\n+          end\n+        end\n+\n+        context \"when it is not successful\" do\n+          before { expect(utils).to receive(:rake).and_return(false) }\n+\n+          it \"does not delete the backup file\" do\n+            expect(File).to receive(:delete).with(uri).never\n+            confirm_and_execute\n+          end\n+\n+          it \"outputs waits for user to press a key to continue\" do\n+            confirm_and_execute\n+            expect_output <<-PROMPT.strip_heredoc\n+\n+              Note: A database restore cannot be undone.  The restore will use the file: #{uri}.\n+              Are you sure you would like to restore the database? (Y/N): \n+              Restoring the database...\n+\n+              Database restore failed. Check the logs for more information\n+\n+              Press any key to continue.\n+            PROMPT\n+          end\n+\n+          context \"without a delete agreement\" do\n+            before do\n+              subject.instance_variable_set(:@delete_agree, false)\n+            end\n+\n+            it \"does not delete the backup file\" do\n+              expect(File).to receive(:delete).with(uri).never\n+              confirm_and_execute\n+            end\n+\n+            it \"outputs waits for user to press a key to continue\" do\n+              confirm_and_execute\n+              expect_output <<-PROMPT.strip_heredoc\n+\n+                Note: A database restore cannot be undone.  The restore will use the file: #{uri}.\n+                Are you sure you would like to restore the database? (Y/N): \n+                Restoring the database...\n+\n+                Database restore failed. Check the logs for more information\n+\n+                Press any key to continue.\n+              PROMPT\n+            end\n+          end\n+        end\n+\n+        context \"when the user aborts\" do\n+          let(:agree) { 'n' }\n+\n+          it \"does not delete the backup file\" do\n+            expect(File).to  receive(:delete).with(uri).never\n+            expect(utils).to receive(:rake).never\n+            confirm_and_execute\n+          end\n+\n+          it \"outputs waits for user to press a key to continue\" do\n+            confirm_and_execute\n+            expect_output <<-PROMPT.strip_heredoc\n+\n+              Note: A database restore cannot be undone.  The restore will use the file: #{uri}.\n+              Are you sure you would like to restore the database? (Y/N): \n+              Press any key to continue.\n+            PROMPT\n+          end\n+        end\n       end\n     end\n   end\n \n-  describe \"#ask_smb_file_options\" do\n-    let(:example_uri) { subject.sample_url('smb') }\n-    let(:user)        { 'example.com/admin' }\n-    let(:pass)        { 'supersecret' }\n-    let(:uri_prompt)  { \"Enter the location of the remote backup file\\nExample: #{example_uri}\" }\n-    let(:user_prompt) { \"Enter the username with access to this file.\\nExample: 'mydomain.com/user'\" }\n-    let(:pass_prompt) { \"Enter the password for #{user}\" }\n-    let(:errmsg)      { \"a valid URI\" }\n-\n-    let(:expected_task_params) do\n-      [\n-        \"--\",\n-        {\n-          :uri          => example_uri,\n-          :uri_username => user,\n-          :uri_password => pass\n-        }\n-      ]\n+  context \"for DB backup\" do\n+    subject { described_class.new(:backup, input, output) }\n+\n+    describe \"#ask_questions\" do\n+      it \"asks for file location, asks to delete backup, runs restore\" do\n+        expect(subject).to receive(:say).with(\"Create Database Backup\\n\\n\")\n+        expect(subject).to receive(:ask_file_location)\n+\n+        subject.ask_questions\n+      end\n     end\n \n-    context \"with a valid uri, username, and password given\" do\n-      before do\n-        say [example_uri, user, pass]\n-        subject.ask_smb_file_options\n+    describe \"#activate\" do\n+      it \"asks for file location, asks to delete backup, runs restore\" do\n+        expect(subject).to receive(:clear_screen)\n+        expect(subject).to receive(:say).with(\"Create Database Backup\\n\\n\")\n+        expect(subject).to receive(:ask_to_delete_backup_after_restore)\n+        expect(subject).to receive(:confirm_and_execute)\n+\n+        subject.activate\n       end\n+    end\n \n-      it \"sets @uri to point to the smb file\" do\n-        expect(subject.uri).to eq(example_uri)\n+    describe \"#ask_file_location\" do\n+      it \"displays the menu\" do\n+        expect(subject).to receive(:ask_local_file_options).once\n+        say \"\"\n+        subject.ask_file_location\n+        expect_output <<-PROMPT.strip_heredoc.chomp + \" \"\n+          Backup File Location\n+\n+          1) Local file\n+          2) Network File System (NFS)\n+          3) Samba (SMB)\n+          4) Cancel\n+\n+          Choose the backup file location: |1|\n+        PROMPT\n+      end\n+\n+      it \"defaults to local file\" do\n+        expect(subject).to receive(:ask_local_file_options).once\n+        say \"\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::LOCAL_FILE)\n+      end\n+\n+      it \"calls #ask_local_file_options when choosen\" do\n+        expect(subject).to receive(:ask_local_file_options).once\n+        say \"1\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::LOCAL_FILE)\n+      end\n+\n+      it \"calls #ask_nfs_file_options when choosen\" do\n+        expect(subject).to receive(:ask_nfs_file_options).once\n+        say \"2\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::NFS_FILE)\n       end\n \n-      it \"sets @task to point to 'evm:db:restore:local'\" do\n-        expect(subject.task).to eq(\"evm:db:restore:remote\")\n+      it \"calls #ask_smb_file_options when choosen\" do\n+        expect(subject).to receive(:ask_smb_file_options).once\n+        say \"3\"\n+        subject.ask_file_location\n+        expect(subject.backup_type).to eq(described_class::SMB_FILE)\n       end\n \n-      it \"sets @task_params to point to the smb file, username, and password\" do\n-        expect(subject.task_params).to eq(expected_task_params)\n+      it \"cancels when CANCEL option is choosen\" do\n+        say \"4\"\n+        expect { subject.ask_file_location }.to raise_error signal_error\n       end\n     end\n \n-    context \"with a invalid uri given\" do\n-      let(:bad_uri) { \"nfs://host.mydomain.com/path/to/file\" }\n+    describe \"#ask_local_file_options\" do\n+      let(:file)      { Tempfile.new(\"foo.backup\").tap(&:close) }\n+      let(:prmpt)     { \"location of the local restore file\" }\n+      let(:default)   { described_class::DB_RESTORE_FILE }\n+      let(:errmsg)    { \"file that exists\" }\n \n-      before do\n-        say [bad_uri, example_uri, user, pass]\n-        subject.ask_smb_file_options\n+      context \"with no filename given\" do\n+        before do\n+          # stub validator for default answer, since it probably doesn't exist on\n+          # the machine running these tests.\n+          stub_const(\"#{described_class.name}::LOCAL_FILE_VALIDATOR\", ->(_) { true })\n+\n+          say \"\"\n+          subject.ask_local_file_options\n+        end\n+\n+        it \"sets @uri to the default filename\" do\n+          expect(subject.uri).to eq(default)\n+        end\n       end\n \n-      it \"reprompts the user and then properly sets the options\" do\n-        error = \"Please provide #{errmsg}\"\n+      context \"with a valid filename given\" do\n+        before do\n+          say file.path.to_s\n+          subject.ask_local_file_options\n+        end\n \n-        expect_readline_question_asked uri_prompt\n-        expect_readline_question_asked user_prompt\n-        expect_heard [\n-          uri_prompt,\n-          error,\n-          prompt,\n-          \"#{pass_prompt}: ***********\\n\"\n-        ]\n+        it \"sets @uri to point to the local file\" do\n+          expect(subject.uri).to eq(file.path)\n+        end\n+\n+        it \"sets @task to point to 'evm:db:backup:local'\" do\n+          expect(subject.task).to eq(\"evm:db:backup:local\")\n+        end\n \n-        expect(subject.uri).to         eq(example_uri)\n-        expect(subject.task).to        eq(\"evm:db:restore:remote\")\n-        expect(subject.task_params).to eq(expected_task_params)\n+        it \"sets @task_params to point to the local file\" do\n+          expect(subject.task_params).to eq([\"--\", {:local_file => file.path}])\n+        end\n+      end\n+\n+      context \"with an invalid filename given\" do\n+        let(:bad_filename) { \"#{file.path}.bad_mmkay\" }\n+\n+        before do\n+          say [bad_filename, file.path.to_s]\n+          subject.ask_local_file_options\n+        end\n+\n+        it \"reprompts the user and then properly sets the options\" do\n+          error = \"Please provide #{errmsg}\"\n+          expect_heard [\"Enter the #{prmpt}: \", error, prompt]\n+\n+          expect(subject.uri).to         eq(file.path)\n+          expect(subject.task).to        eq(\"evm:db:backup:local\")\n+          expect(subject.task_params).to eq([\"--\", {:local_file => file.path}])\n+        end\n       end\n     end\n-  end\n \n-  describe \"#ask_to_delete_backup_after_restore\" do\n-    context \"when @backup_type is LOCAL_FILE\" do\n-      let(:uri) { described_class::DB_RESTORE_FILE }\n+    describe \"#ask_nfs_file_options\" do\n+      let(:example_uri) { subject.sample_url('nfs') }\n+      let(:prmpt)       { \"location of the remote backup file\\nExample: #{example_uri}\" }\n+      let(:errmsg)      { \"a valid URI\" }\n \n-      before do\n-        subject.instance_variable_set(:@uri, uri)\n-        subject.instance_variable_set(:@backup_type, described_class::LOCAL_FILE)\n+      context \"with a valid uri given\" do\n+        before do\n+          say example_uri\n+          subject.ask_nfs_file_options\n+        end\n+\n+        it \"sets @uri to point to the nfs file\" do\n+          expect(subject.uri).to eq(example_uri)\n+        end\n+\n+        it \"sets @task to point to 'evm:db:backup:remote'\" do\n+          expect(subject.task).to eq(\"evm:db:backup:remote\")\n+        end\n+\n+        it \"sets @task_params to point to the nfs file\" do\n+          expect(subject.task_params).to eq([\"--\", {:uri => example_uri}])\n+        end\n       end\n \n-      it \"sets @delete_agree if the user agrees\" do\n-        say \"y\"\n-        subject.ask_to_delete_backup_after_restore\n-        expect_output <<-PROMPT.strip_heredoc.chomp + \" \"\n-          The local database restore file is located at: '#{uri}'.\n-          Should this file be deleted after completing the restore? (Y/N):\n-        PROMPT\n+      context \"with an invalid uri given\" do\n+        let(:bad_uri) { \"file://host.mydomain.com/path/to/file\" }\n+\n+        before do\n+          say [bad_uri, example_uri]\n+          subject.ask_nfs_file_options\n+        end\n+\n+        it \"reprompts the user and then properly sets the options\" do\n+          error = \"Please provide #{errmsg}\"\n+          expect_heard [\"Enter the #{prmpt}: \", error, prompt]\n+\n+          expect(subject.uri).to         eq(example_uri)\n+          expect(subject.task).to        eq(\"evm:db:backup:remote\")\n+          expect(subject.task_params).to eq([\"--\", {:uri => example_uri}])\n+        end\n+      end\n+    end\n+\n+    describe \"#ask_smb_file_options\" do\n+      let(:example_uri) { subject.sample_url('smb') }\n+      let(:user)        { 'example.com/admin' }\n+      let(:pass)        { 'supersecret' }\n+      let(:uri_prompt)  { \"Enter the location of the remote backup file\\nExample: #{example_uri}\" }\n+      let(:user_prompt) { \"Enter the username with access to this file.\\nExample: 'mydomain.com/user'\" }\n+      let(:pass_prompt) { \"Enter the password for #{user}\" }\n+      let(:errmsg)      { \"a valid URI\" }\n+\n+      let(:expected_task_params) do\n+        [\n+          \"--\",\n+          {\n+            :uri          => example_uri,\n+            :uri_username => user,\n+            :uri_password => pass\n+          }\n+        ]\n       end\n \n-      it \"sets @delete_agree to true if the user agrees\" do\n-        say \"y\"\n-        subject.ask_to_delete_backup_after_restore\n-        expect(subject.delete_agree).to eq(true)\n+      context \"with a valid uri, username, and password given\" do\n+        before do\n+          say [example_uri, user, pass]\n+          subject.ask_smb_file_options\n+        end\n+\n+        it \"sets @uri to point to the smb file\" do\n+          expect(subject.uri).to eq(example_uri)\n+        end\n+\n+        it \"sets @task to point to 'evm:db:backup:local'\" do\n+          expect(subject.task).to eq(\"evm:db:backup:remote\")\n+        end\n+\n+        it \"sets @task_params to point to the smb file, username, and password\" do\n+          expect(subject.task_params).to eq(expected_task_params)\n+        end\n       end\n \n-      it \"sets @delete_agree to false if the user disagrees\" do\n-        say \"n\"\n-        subject.ask_to_delete_backup_after_restore\n-        expect(subject.delete_agree).to eq(false)\n+      context \"with a invalid uri given\" do\n+        let(:bad_uri) { \"nfs://host.mydomain.com/path/to/file\" }\n+\n+        before do\n+          say [bad_uri, example_uri, user, pass]\n+          subject.ask_smb_file_options\n+        end\n+\n+        it \"reprompts the user and then properly sets the options\" do\n+          error = \"Please provide #{errmsg}\"\n+\n+          expect_readline_question_asked uri_prompt\n+          expect_readline_question_asked user_prompt\n+          expect_heard [\n+            uri_prompt,\n+            error,\n+            prompt,\n+            \"#{pass_prompt}: ***********\\n\"\n+          ]\n+\n+          expect(subject.uri).to         eq(example_uri)\n+          expect(subject.task).to        eq(\"evm:db:backup:remote\")\n+          expect(subject.task_params).to eq(expected_task_params)\n+        end\n       end\n     end\n \n-    context \"when @backup_type not is LOCAL_FILE\" do\n-      let(:uri) { described_class::DB_RESTORE_FILE }\n+    describe \"#ask_to_delete_backup_after_restore\" do","path":"spec/database_admin_spec.rb","position":878,"original_position":878,"commit_id":"c1303ebff01a4ee122d287df44488645de43e32f","original_commit_id":"c1303ebff01a4ee122d287df44488645de43e32f","user":{"login":"carbonin","id":12697904,"avatar_url":"https://avatars0.githubusercontent.com/u/12697904?v=4","gravatar_id":"","url":"https://api.github.com/users/carbonin","html_url":"https://github.com/carbonin","followers_url":"https://api.github.com/users/carbonin/followers","following_url":"https://api.github.com/users/carbonin/following{/other_user}","gists_url":"https://api.github.com/users/carbonin/gists{/gist_id}","starred_url":"https://api.github.com/users/carbonin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carbonin/subscriptions","organizations_url":"https://api.github.com/users/carbonin/orgs","repos_url":"https://api.github.com/users/carbonin/repos","events_url":"https://api.github.com/users/carbonin/events{/privacy}","received_events_url":"https://api.github.com/users/carbonin/received_events","type":"User","site_admin":false},"body":"Is this in the \"for DB backup\" context? I think this is restore related.","created_at":"2018-05-25T18:42:11Z","updated_at":"2018-05-25T18:46:40Z","html_url":"https://github.com/ManageIQ/manageiq-appliance_console/pull/44#discussion_r190979103","pull_request_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/comments/190979103"},"html":{"href":"https://github.com/ManageIQ/manageiq-appliance_console/pull/44#discussion_r190979103"},"pull_request":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44"}}},"pull_request":{"url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44","id":190661052,"html_url":"https://github.com/ManageIQ/manageiq-appliance_console/pull/44","diff_url":"https://github.com/ManageIQ/manageiq-appliance_console/pull/44.diff","patch_url":"https://github.com/ManageIQ/manageiq-appliance_console/pull/44.patch","issue_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues/44","number":44,"state":"open","locked":false,"title":"Add dbbackup action","user":{"login":"NickLaMuro","id":314014,"avatar_url":"https://avatars0.githubusercontent.com/u/314014?v=4","gravatar_id":"","url":"https://api.github.com/users/NickLaMuro","html_url":"https://github.com/NickLaMuro","followers_url":"https://api.github.com/users/NickLaMuro/followers","following_url":"https://api.github.com/users/NickLaMuro/following{/other_user}","gists_url":"https://api.github.com/users/NickLaMuro/gists{/gist_id}","starred_url":"https://api.github.com/users/NickLaMuro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NickLaMuro/subscriptions","organizations_url":"https://api.github.com/users/NickLaMuro/orgs","repos_url":"https://api.github.com/users/NickLaMuro/repos","events_url":"https://api.github.com/users/NickLaMuro/events{/privacy}","received_events_url":"https://api.github.com/users/NickLaMuro/received_events","type":"User","site_admin":false},"body":"This is built off of https://github.com/ManageIQ/manageiq-appliance_console/pull/42 and adds new functionality to trigger `evm:db:backup:local` and `evm:db:backup:remote`, with identical options for file location as `restore` (Local file, NFS, and SMB).\r\n\r\nThis basically slightly modifies the `DatabaseAdmin` class to support an `action` accessor, which allows the `bin/appliance_console` to choose between doing a `:restore` or a `:backup`.  From there, it is simply choosing the right file options and such from the menu in the same fashion as for `restore`.\r\n\r\n\r\nLinks\r\n-----\r\n\r\n* Tangentially related to https://bugzilla.redhat.com/show_bug.cgi?id=1535345\r\n* Built off of https://github.com/ManageIQ/manageiq-appliance_console/pull/42\r\n* [Previous diff](https://github.com/ManageIQ/manageiq-appliance_console/compare/3f49d2de27e487e9d6b79d8261d45204be5e5281...NickLaMuro:rfe-db-dump-from-appliance-console-menu-orig) of this combined with #42 (prior to feedback)","created_at":"2018-05-25T18:16:19Z","updated_at":"2018-05-25T18:46:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"63ddf14b11374a68beaa9cfbbab8ee1dd380ead6","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44/commits","review_comments_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44/comments","review_comment_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues/44/comments","statuses_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/statuses/c1303ebff01a4ee122d287df44488645de43e32f","head":{"label":"NickLaMuro:rfe-db-dump-from-appliance-console-menu-part-2","ref":"rfe-db-dump-from-appliance-console-menu-part-2","sha":"c1303ebff01a4ee122d287df44488645de43e32f","user":{"login":"NickLaMuro","id":314014,"avatar_url":"https://avatars0.githubusercontent.com/u/314014?v=4","gravatar_id":"","url":"https://api.github.com/users/NickLaMuro","html_url":"https://github.com/NickLaMuro","followers_url":"https://api.github.com/users/NickLaMuro/followers","following_url":"https://api.github.com/users/NickLaMuro/following{/other_user}","gists_url":"https://api.github.com/users/NickLaMuro/gists{/gist_id}","starred_url":"https://api.github.com/users/NickLaMuro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NickLaMuro/subscriptions","organizations_url":"https://api.github.com/users/NickLaMuro/orgs","repos_url":"https://api.github.com/users/NickLaMuro/repos","events_url":"https://api.github.com/users/NickLaMuro/events{/privacy}","received_events_url":"https://api.github.com/users/NickLaMuro/received_events","type":"User","site_admin":false},"repo":{"id":110608487,"name":"manageiq-appliance_console","full_name":"NickLaMuro/manageiq-appliance_console","owner":{"login":"NickLaMuro","id":314014,"avatar_url":"https://avatars0.githubusercontent.com/u/314014?v=4","gravatar_id":"","url":"https://api.github.com/users/NickLaMuro","html_url":"https://github.com/NickLaMuro","followers_url":"https://api.github.com/users/NickLaMuro/followers","following_url":"https://api.github.com/users/NickLaMuro/following{/other_user}","gists_url":"https://api.github.com/users/NickLaMuro/gists{/gist_id}","starred_url":"https://api.github.com/users/NickLaMuro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NickLaMuro/subscriptions","organizations_url":"https://api.github.com/users/NickLaMuro/orgs","repos_url":"https://api.github.com/users/NickLaMuro/repos","events_url":"https://api.github.com/users/NickLaMuro/events{/privacy}","received_events_url":"https://api.github.com/users/NickLaMuro/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/NickLaMuro/manageiq-appliance_console","description":"The console for the ManageIQ appliances.","fork":true,"url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console","forks_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/forks","keys_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/teams","hooks_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/hooks","issue_events_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/issues/events{/number}","events_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/events","assignees_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/assignees{/user}","branches_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/branches{/branch}","tags_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/tags","blobs_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/git/refs{/sha}","trees_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/statuses/{sha}","languages_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/languages","stargazers_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/stargazers","contributors_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/contributors","subscribers_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/subscribers","subscription_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/subscription","commits_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/commits{/sha}","git_commits_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/git/commits{/sha}","comments_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/comments{/number}","issue_comment_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/issues/comments{/number}","contents_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/contents/{+path}","compare_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/merges","archive_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/downloads","issues_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/issues{/number}","pulls_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/pulls{/number}","milestones_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/milestones{/number}","notifications_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/labels{/name}","releases_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/releases{/id}","deployments_url":"https://api.github.com/repos/NickLaMuro/manageiq-appliance_console/deployments","created_at":"2017-11-13T22:11:41Z","updated_at":"2018-05-04T14:29:32Z","pushed_at":"2018-05-25T18:29:57Z","git_url":"git://github.com/NickLaMuro/manageiq-appliance_console.git","ssh_url":"git@github.com:NickLaMuro/manageiq-appliance_console.git","clone_url":"https://github.com/NickLaMuro/manageiq-appliance_console.git","svn_url":"https://github.com/NickLaMuro/manageiq-appliance_console","homepage":null,"size":420,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ManageIQ:master","ref":"master","sha":"d62387e47a7d28adc094c6f50cf64dd2b7adba59","user":{"login":"ManageIQ","id":1125575,"avatar_url":"https://avatars0.githubusercontent.com/u/1125575?v=4","gravatar_id":"","url":"https://api.github.com/users/ManageIQ","html_url":"https://github.com/ManageIQ","followers_url":"https://api.github.com/users/ManageIQ/followers","following_url":"https://api.github.com/users/ManageIQ/following{/other_user}","gists_url":"https://api.github.com/users/ManageIQ/gists{/gist_id}","starred_url":"https://api.github.com/users/ManageIQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ManageIQ/subscriptions","organizations_url":"https://api.github.com/users/ManageIQ/orgs","repos_url":"https://api.github.com/users/ManageIQ/repos","events_url":"https://api.github.com/users/ManageIQ/events{/privacy}","received_events_url":"https://api.github.com/users/ManageIQ/received_events","type":"Organization","site_admin":false},"repo":{"id":107316888,"name":"manageiq-appliance_console","full_name":"ManageIQ/manageiq-appliance_console","owner":{"login":"ManageIQ","id":1125575,"avatar_url":"https://avatars0.githubusercontent.com/u/1125575?v=4","gravatar_id":"","url":"https://api.github.com/users/ManageIQ","html_url":"https://github.com/ManageIQ","followers_url":"https://api.github.com/users/ManageIQ/followers","following_url":"https://api.github.com/users/ManageIQ/following{/other_user}","gists_url":"https://api.github.com/users/ManageIQ/gists{/gist_id}","starred_url":"https://api.github.com/users/ManageIQ/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ManageIQ/subscriptions","organizations_url":"https://api.github.com/users/ManageIQ/orgs","repos_url":"https://api.github.com/users/ManageIQ/repos","events_url":"https://api.github.com/users/ManageIQ/events{/privacy}","received_events_url":"https://api.github.com/users/ManageIQ/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ManageIQ/manageiq-appliance_console","description":"The console for the ManageIQ appliances.","fork":false,"url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console","forks_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/forks","keys_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/teams","hooks_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/hooks","issue_events_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues/events{/number}","events_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/events","assignees_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/assignees{/user}","branches_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/branches{/branch}","tags_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/tags","blobs_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/git/refs{/sha}","trees_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/statuses/{sha}","languages_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/languages","stargazers_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/stargazers","contributors_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/contributors","subscribers_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/subscribers","subscription_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/subscription","commits_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/commits{/sha}","git_commits_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/git/commits{/sha}","comments_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/comments{/number}","issue_comment_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues/comments{/number}","contents_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/contents/{+path}","compare_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/merges","archive_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/downloads","issues_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues{/number}","pulls_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls{/number}","milestones_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/milestones{/number}","notifications_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/labels{/name}","releases_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/releases{/id}","deployments_url":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/deployments","created_at":"2017-10-17T19:52:01Z","updated_at":"2018-05-25T17:46:05Z","pushed_at":"2018-05-25T18:29:58Z","git_url":"git://github.com/ManageIQ/manageiq-appliance_console.git","ssh_url":"git@github.com:ManageIQ/manageiq-appliance_console.git","clone_url":"https://github.com/ManageIQ/manageiq-appliance_console.git","svn_url":"https://github.com/ManageIQ/manageiq-appliance_console","homepage":null,"size":32394,"stargazers_count":3,"watchers_count":3,"language":"Ruby","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":18,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":18,"open_issues":5,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44"},"html":{"href":"https://github.com/ManageIQ/manageiq-appliance_console/pull/44"},"issue":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues/44"},"comments":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/issues/44/comments"},"review_comments":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44/comments"},"review_comment":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/pulls/44/commits"},"statuses":{"href":"https://api.github.com/repos/ManageIQ/manageiq-appliance_console/statuses/c1303ebff01a4ee122d287df44488645de43e32f"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"carbonin"}}