mirror of
https://github.com/hashicorp/vagrant.git
synced 2026-05-28 04:36:05 -04:00
Remove customized require behaviors and modify the bin executable to check for missing tools that Vagrant expects to exist when running outside of an installer.
206 lines
7.6 KiB
Ruby
206 lines
7.6 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
require 'optparse'
|
|
|
|
require_relative 'download_mixins'
|
|
|
|
module VagrantPlugins
|
|
module CommandBox
|
|
module Command
|
|
class Update < Vagrant.plugin("2", :command)
|
|
include DownloadMixins
|
|
|
|
def execute
|
|
options = {}
|
|
download_options = {}
|
|
|
|
opts = OptionParser.new do |o|
|
|
o.banner = "Usage: vagrant box update [options]"
|
|
o.separator ""
|
|
o.separator "Updates the box that is in use in the current Vagrant environment,"
|
|
o.separator "if there any updates available. This does not destroy/recreate the"
|
|
o.separator "machine, so you'll have to do that to see changes."
|
|
o.separator ""
|
|
o.separator "To update a specific box (not tied to a Vagrant environment), use the"
|
|
o.separator "--box flag."
|
|
o.separator ""
|
|
o.separator "Options:"
|
|
o.separator ""
|
|
|
|
o.on("--box BOX", String, "Update a specific box") do |b|
|
|
options[:box] = b
|
|
end
|
|
|
|
o.on("--architecture ARCHITECTURE", String, "Update box with specific architecture") do |a|
|
|
options[:architecture] = a
|
|
end
|
|
|
|
o.on("--provider PROVIDER", String, "Update box with specific provider") do |p|
|
|
options[:provider] = p.to_sym
|
|
end
|
|
|
|
o.on("-f", "--force", "Overwrite an existing box if it exists") do |f|
|
|
options[:force] = f
|
|
end
|
|
|
|
build_download_options(o, download_options)
|
|
end
|
|
|
|
argv = parse_options(opts)
|
|
return if !argv
|
|
|
|
if options[:box]
|
|
update_specific(options[:box], options[:provider], options[:architecture], download_options, options[:force])
|
|
else
|
|
update_vms(argv, options[:provider], download_options, options[:force])
|
|
end
|
|
|
|
0
|
|
end
|
|
|
|
def update_specific(name, provider, architecture, download_options, force)
|
|
box_info = Vagrant::Util::HashWithIndifferentAccess.new
|
|
@env.boxes.all.each do |box_name, box_version, box_provider, box_architecture|
|
|
next if name != box_name
|
|
box_info[box_provider] ||= Vagrant::Util::HashWithIndifferentAccess.new
|
|
box_info[box_provider][box_version] ||= []
|
|
box_info[box_provider][box_version].push(box_architecture.to_s).uniq!
|
|
end
|
|
|
|
if box_info.empty?
|
|
raise Vagrant::Errors::BoxNotFound, name: name.to_s
|
|
end
|
|
|
|
if !provider
|
|
if box_info.size > 1
|
|
raise Vagrant::Errors::BoxUpdateMultiProvider,
|
|
name: name.to_s,
|
|
providers: box_info.keys.map(&:to_s).sort.join(", ")
|
|
end
|
|
|
|
provider = box_info.keys.first
|
|
elsif !box_info[provider]
|
|
raise Vagrant::Errors::BoxNotFoundWithProvider,
|
|
name: name.to_s,
|
|
provider: provider.to_s,
|
|
providers: box_info.keys.map(&:to_s).sort.join(", ")
|
|
end
|
|
|
|
version = box_info[provider].keys.sort_by{ |v| Gem::Version.new(v) }.last
|
|
architecture_list = box_info[provider][version]
|
|
|
|
if !architecture
|
|
if architecture_list.size > 1
|
|
raise Vagrant::Errors::BoxUpdateMultiArchitecture,
|
|
name: name.to_s,
|
|
provider: provider.to_s,
|
|
version: version.to_s,
|
|
architectures: architecture_list.sort.join(", ")
|
|
end
|
|
|
|
architecture = architecture_list.first
|
|
elsif !architecture_list.include?(architecture)
|
|
raise Vagrant::Errors::BoxNotFoundWithProviderArchitecture,
|
|
name: name.to_s,
|
|
provider: provider.to_s,
|
|
version: version.to_s,
|
|
architecture: architecture,
|
|
architectures: architecture_list.sort.join(", ")
|
|
end
|
|
|
|
# Architecture gets cast to a string when collecting information
|
|
# above. Convert it back to a nil if it's empty
|
|
architecture = nil if architecture.to_s.empty?
|
|
|
|
box = @env.boxes.find(name, provider, version, architecture)
|
|
box_update(box, "> #{version}", @env.ui, download_options, force)
|
|
end
|
|
|
|
def update_vms(argv, provider, download_options, force)
|
|
machines = {}
|
|
|
|
with_target_vms(argv, provider: provider) do |machine|
|
|
if !machine.config.vm.box
|
|
machine.ui.output(I18n.t(
|
|
"vagrant.errors.box_update_no_name"))
|
|
next
|
|
end
|
|
|
|
if !machine.box
|
|
collection = Vagrant::BoxCollection.new(@env.boxes_path)
|
|
machine.box = collection.find(machine.config.vm.box, provider || machine.provider_name || @env.default_provider, "> 0")
|
|
if !machine.box
|
|
machine.ui.output(I18n.t(
|
|
"vagrant.errors.box_update_no_box",
|
|
name: machine.config.vm.box))
|
|
next
|
|
end
|
|
end
|
|
|
|
name = machine.box.name
|
|
provider = machine.box.provider
|
|
version = machine.config.vm.box_version || machine.box.version
|
|
|
|
machines["#{name}_#{provider}_#{version}"] = machine
|
|
end
|
|
|
|
machines.each do |_, machine|
|
|
box = machine.box
|
|
version = machine.config.vm.box_version
|
|
# Get download options from machine configuration if not specified
|
|
# on the command line.
|
|
download_options[:ca_cert] ||= machine.config.vm.box_download_ca_cert
|
|
download_options[:ca_path] ||= machine.config.vm.box_download_ca_path
|
|
download_options[:client_cert] ||= machine.config.vm.box_download_client_cert
|
|
if download_options[:insecure].nil?
|
|
download_options[:insecure] = machine.config.vm.box_download_insecure
|
|
end
|
|
|
|
begin
|
|
box_update(box, version, machine.ui, download_options, force)
|
|
rescue Vagrant::Errors::BoxUpdateNoMetadata => e
|
|
machine.ui.warn(e)
|
|
next
|
|
end
|
|
end
|
|
end
|
|
|
|
def box_update(box, version, ui, download_options, force)
|
|
ui.output(I18n.t("vagrant.box_update_checking", name: box.name))
|
|
ui.detail("Latest installed version: #{box.version}")
|
|
ui.detail("Version constraints: #{version}")
|
|
ui.detail("Provider: #{box.provider}")
|
|
ui.detail("Architecture: #{box.architecture.inspect}") if box.architecture
|
|
|
|
update = box.has_update?(version, download_options: download_options)
|
|
if !update
|
|
ui.success(I18n.t(
|
|
"vagrant.box_up_to_date_single",
|
|
name: box.name, version: box.version))
|
|
return
|
|
end
|
|
|
|
ui.output(I18n.t(
|
|
"vagrant.box_updating",
|
|
name: update[0].name,
|
|
provider: update[2].name,
|
|
old: box.version,
|
|
new: update[1].version))
|
|
@env.action_runner.run(Vagrant::Action.action_box_add, {
|
|
box_url: box.metadata_url,
|
|
box_provider: update[2].name,
|
|
box_version: update[1].version,
|
|
box_architecture: update[2].architecture,
|
|
ui: ui,
|
|
box_force: force,
|
|
box_download_client_cert: download_options[:client_cert],
|
|
box_download_ca_cert: download_options[:ca_cert],
|
|
box_download_ca_path: download_options[:ca_path],
|
|
box_download_insecure: download_options[:insecure]
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|