From bcf4d5a210ca67af2312dea2e6c758463a9f5777 Mon Sep 17 00:00:00 2001
From: Brian Cain <bcain@hashicorp.com>
Date: Tue, 3 Dec 2019 11:42:55 -0800
Subject: [PATCH] Fixes #11228: Allow to force check for box updates

Prior to this commit, if a user had recently checked for updates, there
was no way to force Vagrant to re-check without manually deleting a
state file in the local `.vagrant` data dir. This commit fixes that by
giving users the ability to force check for updates for a given box with
a flag to the `vagrant box outdated` command.
---
 lib/vagrant/action/builtin/box_check_outdated.rb |  2 +-
 plugins/commands/box/command/outdated.rb         |  6 +++++-
 .../commands/box/command/outdated_test.rb        | 16 ++++++++++++----
 .../action/builtin/box_check_outdated_test.rb    | 10 ++++++++++
 website/source/docs/cli/box.html.md              |  5 +++++
 5 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/lib/vagrant/action/builtin/box_check_outdated.rb b/lib/vagrant/action/builtin/box_check_outdated.rb
index de3468d76..e941f2fc5 100644
--- a/lib/vagrant/action/builtin/box_check_outdated.rb
+++ b/lib/vagrant/action/builtin/box_check_outdated.rb
@@ -40,7 +40,7 @@ module Vagrant
           # Have download options specified in the environment override
           # options specified for the machine.
           download_options = {
-            automatic_check: true,
+            automatic_check: !env[:box_outdated_force],
             ca_cert: env[:ca_cert] || machine.config.vm.box_download_ca_cert,
             ca_path: env[:ca_path] || machine.config.vm.box_download_ca_path,
             client_cert: env[:client_cert] ||
diff --git a/plugins/commands/box/command/outdated.rb b/plugins/commands/box/command/outdated.rb
index f9ab9f146..549c4c643 100644
--- a/plugins/commands/box/command/outdated.rb
+++ b/plugins/commands/box/command/outdated.rb
@@ -26,6 +26,10 @@ module VagrantPlugins
               options[:global] = g
             end
 
+            o.on("-f", "--force", "Force checks for latest box updates") do |f|
+              options[:force] = f
+            end
+
             build_download_options(o, download_options)
           end
 
@@ -40,7 +44,7 @@ module VagrantPlugins
 
           with_target_vms(argv) do |machine|
             @env.action_runner.run(Vagrant::Action.action_box_outdated, {
-              box_outdated_force: true,
+              box_outdated_force: options[:force],
               box_outdated_refresh: true,
               box_outdated_success_ui: true,
               machine: machine,
diff --git a/test/unit/plugins/commands/box/command/outdated_test.rb b/test/unit/plugins/commands/box/command/outdated_test.rb
index dc5ea60d3..c395171aa 100644
--- a/test/unit/plugins/commands/box/command/outdated_test.rb
+++ b/test/unit/plugins/commands/box/command/outdated_test.rb
@@ -20,6 +20,18 @@ describe VagrantPlugins::CommandBox::Command::Outdated do
     allow(iso_env).to receive(:action_runner).and_return(action_runner)
   end
 
+  context "with force argument" do
+    let(:argv) { ["--force"] }
+
+    it "passes along the force update option" do
+      expect(action_runner).to receive(:run).with(any_args) { |action, **opts|
+        expect(opts[:box_outdated_force]).to be_truthy
+        true
+      }
+      subject.execute
+    end
+  end
+
   context "with global argument" do
     let(:argv) { ["--global"] }
 
@@ -29,10 +41,6 @@ describe VagrantPlugins::CommandBox::Command::Outdated do
       subject.execute
     end
 
-    before do
-
-    end
-
     describe ".outdated_global" do
       let(:test_iso_env) { isolated_environment }
 
diff --git a/test/unit/vagrant/action/builtin/box_check_outdated_test.rb b/test/unit/vagrant/action/builtin/box_check_outdated_test.rb
index 190b126f8..bb55f26c6 100644
--- a/test/unit/vagrant/action/builtin/box_check_outdated_test.rb
+++ b/test/unit/vagrant/action/builtin/box_check_outdated_test.rb
@@ -54,11 +54,21 @@ describe Vagrant::Action::Builtin::BoxCheckOutdated do
       env[:box_outdated_force] = true
 
       expect(app).to receive(:call).with(env).once
+      expect(box).to receive(:has_update?)
 
       subject.call(env)
 
       expect(env).to have_key(:box_outdated)
     end
+
+    it "checks if not forced" do
+      machine.config.vm.box_check_update = false
+      env[:box_outdated_force] = false
+
+      expect(app).to receive(:call).with(env).once
+
+      subject.call(env)
+    end
   end
 
   context "no box" do
diff --git a/website/source/docs/cli/box.html.md b/website/source/docs/cli/box.html.md
index 2c65a6d6c..ae4bf6341 100644
--- a/website/source/docs/cli/box.html.md
+++ b/website/source/docs/cli/box.html.md
@@ -125,8 +125,13 @@ which may be different than the absolute latest version available.
 Checking for updates involves refreshing the metadata associated with
 a box. This generally requires an internet connection.
 
+By default, if Vagrant has recently checked for a box that's out of date, it will
+cache that answer and not look up another update for one hour. This cached value
+can be ignored if the `--force` flag is used.
+
 ## Options
 
+* `--force` - Check for updates for all installed boxes and ignore cache interval.
 * `--global` - Check for updates for all installed boxes, not just the
   boxes for the current Vagrant environment.