Introduce `cloud` command
This commit adds a new command to Vagrant called `cloud`. It handles any and all interactions with the external service Vagrant Cloud.
This commit is contained in:
parent
dd3d6c7cf2
commit
e70b871660
|
@ -61,6 +61,13 @@ if ENV["VAGRANT_LOG"] && ENV["VAGRANT_LOG"] != ""
|
|||
end
|
||||
Log4r::Outputter.stderr.formatter = Vagrant::Util::LoggingFormatter.new(base_formatter)
|
||||
logger = nil
|
||||
|
||||
# Cloud gem uses RestClient to make HTTP requests, so
|
||||
# log them if debug is enabled
|
||||
if level == 1
|
||||
# TODO: Need to ensure token is marked sensitive, if possible here
|
||||
ENV["RESTCLIENT_LOG"] = "stdout"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module AuthCommand
|
||||
module Command
|
||||
class Login < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud auth login [options]"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on("-c", "--check", "Only checks if you're logged in") do |c|
|
||||
options[:check] = c
|
||||
end
|
||||
|
||||
o.on("-d", "--description DESCRIPTION", String, "Description for the Vagrant Cloud token") do |d|
|
||||
options[:description] = d
|
||||
end
|
||||
|
||||
o.on("-k", "--logout", "Logs you out if you're logged in") do |k|
|
||||
options[:logout] = k
|
||||
end
|
||||
|
||||
o.on("-t", "--token TOKEN", String, "Set the Vagrant Cloud token") do |t|
|
||||
options[:token] = t
|
||||
end
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |l|
|
||||
options[:login] = l
|
||||
end
|
||||
end
|
||||
# TODO: Should be an alias for the existing login command
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
@client = Client.new(@env)
|
||||
@client.username_or_email = options[:login]
|
||||
|
||||
# Determine what task we're actually taking based on flags
|
||||
if options[:check]
|
||||
return execute_check
|
||||
elsif options[:logout]
|
||||
return execute_logout
|
||||
elsif options[:token]
|
||||
return execute_token(options[:token])
|
||||
else
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options)
|
||||
end
|
||||
|
||||
0
|
||||
end
|
||||
|
||||
def execute_check
|
||||
if @client.logged_in?
|
||||
@env.ui.success(I18n.t("cloud_command.check_logged_in"))
|
||||
return 0
|
||||
else
|
||||
@env.ui.error(I18n.t("cloud_command.check_not_logged_in"))
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
def execute_logout
|
||||
@client.clear_token
|
||||
@env.ui.success(I18n.t("cloud_command.logged_out"))
|
||||
return 0
|
||||
end
|
||||
|
||||
def execute_token(token)
|
||||
@client.store_token(token)
|
||||
@env.ui.success(I18n.t("cloud_command.token_saved"))
|
||||
|
||||
if @client.logged_in?
|
||||
@env.ui.success(I18n.t("cloud_command.check_logged_in"))
|
||||
return 0
|
||||
else
|
||||
@env.ui.error(I18n.t("cloud_command.invalid_token"))
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module AuthCommand
|
||||
module Command
|
||||
class Logout < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud auth logout [options]"
|
||||
o.separator ""
|
||||
o.separator "Logs you out if you're logged in locally."
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |l|
|
||||
options[:login] = l
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.length > 1
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
# Initializes client and deletes token on disk
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
@client.clear_token
|
||||
@env.ui.success(I18n.t("cloud_command.logged_out"))
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module AuthCommand
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "vagrant cloud auth"
|
||||
description <<-DESC
|
||||
Authorization commands for Vagrant Cloud
|
||||
DESC
|
||||
|
||||
command(:auth) do
|
||||
require_relative "root"
|
||||
Command::Root
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module AuthCommand
|
||||
module Command
|
||||
class Root < Vagrant.plugin("2", :command)
|
||||
def self.synopsis
|
||||
"Manages everything authorization related to Vagrant Cloud"
|
||||
end
|
||||
|
||||
def initialize(argv, env)
|
||||
super
|
||||
|
||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||
@subcommands = Vagrant::Registry.new
|
||||
@subcommands.register(:login) do
|
||||
require File.expand_path("../login", __FILE__)
|
||||
Command::Login
|
||||
end
|
||||
@subcommands.register(:logout) do
|
||||
require File.expand_path("../logout", __FILE__)
|
||||
Command::Logout
|
||||
end
|
||||
@subcommands.register(:whoami) do
|
||||
require File.expand_path("../whoami", __FILE__)
|
||||
Command::Whoami
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
if @main_args.include?("-h") || @main_args.include?("--help")
|
||||
# Print the help for all the box commands.
|
||||
return help
|
||||
end
|
||||
|
||||
# If we reached this far then we must have a subcommand. If not,
|
||||
# then we also just print the help and exit.
|
||||
command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
|
||||
return help if !command_class || !@sub_command
|
||||
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
||||
|
||||
# Initialize and execute the command class
|
||||
command_class.new(@sub_args, @env).execute
|
||||
end
|
||||
|
||||
# Prints the help out for this command
|
||||
def help
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: vagrant cloud auth <subcommand> [<args>]"
|
||||
opts.separator ""
|
||||
opts.separator "Helper commands for authorization with Vagrant Cloud"
|
||||
opts.separator ""
|
||||
opts.separator "Available subcommands:"
|
||||
|
||||
# Add the available subcommands as separators in order to print them
|
||||
# out as well.
|
||||
keys = []
|
||||
@subcommands.each { |key, value| keys << key.to_s }
|
||||
|
||||
keys.sort.each do |key|
|
||||
opts.separator " #{key}"
|
||||
end
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "For help on any individual subcommand run `vagrant cloud auth <subcommand> -h`"
|
||||
end
|
||||
|
||||
@env.ui.info(opts.help, prefix: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module AuthCommand
|
||||
module Command
|
||||
class Whoami < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud auth whoami [options] [token]"
|
||||
o.separator ""
|
||||
o.separator "Determine who you are logged in as"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |l|
|
||||
options[:login] = l
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.size > 1
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
if argv.first
|
||||
token = argv.first
|
||||
else
|
||||
token = @client.token
|
||||
end
|
||||
|
||||
whoami(token, options[:username])
|
||||
end
|
||||
|
||||
def whoami(access_token, username)
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(username, access_token, server_url)
|
||||
|
||||
begin
|
||||
success = account.validate_token
|
||||
user = success["user"]["username"]
|
||||
@env.ui.success("Currently logged in as #{user}")
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.whoami.read_error", org: username))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module BoxCommand
|
||||
module Command
|
||||
class Create < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud box create [options] organization/box-name"
|
||||
o.separator ""
|
||||
o.separator "Creates an empty box entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-d", "--description DESCRIPTION", String, "Longer description of the box") do |d|
|
||||
options[:description] = d
|
||||
end
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
o.on("-s", "--short-description DESCRIPTION", String, "Short description of the box") do |s|
|
||||
options[:short] = s
|
||||
end
|
||||
o.on("-p", "--private", "Makes box private") do |p|
|
||||
options[:private] = p
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
create_box(org, box_name, options, @client.token)
|
||||
end
|
||||
|
||||
# @param [String] - org
|
||||
# @param [String] - box_name
|
||||
# @param [Hash] - options
|
||||
def create_box(org, box_name, options, access_token)
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, options[:short], options[:description], access_token)
|
||||
|
||||
begin
|
||||
success = box.create
|
||||
@env.ui.success(I18n.t("cloud_command.box.create_success", org: org, box_name: box_name))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.box.create_fail", org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,65 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module BoxCommand
|
||||
module Command
|
||||
class Delete < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud box delete [options] organization/box-name"
|
||||
o.separator ""
|
||||
o.separator "Deletes box entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@env.ui.warn(I18n.t("cloud_command.box.delete_warn", box: argv.first))
|
||||
continue = @env.ui.ask(I18n.t("cloud_command.continue"))
|
||||
return 1 if continue.downcase != "y"
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
delete_box(org, box_name, options[:username], @client.token)
|
||||
end
|
||||
|
||||
def delete_box(org, box_name, username, access_token)
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(username, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
|
||||
begin
|
||||
success = box.delete(org, box_name)
|
||||
@env.ui.success(I18n.t("cloud_command.box.delete_success", org: org, box_name: box_name))
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.box.delete_fail", org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module BoxCommand
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "vagrant cloud box"
|
||||
description <<-DESC
|
||||
Box CRUD commands for Vagrant Cloud
|
||||
DESC
|
||||
|
||||
command(:box) do
|
||||
require_relative "root"
|
||||
Command::Root
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module BoxCommand
|
||||
module Command
|
||||
class Root < Vagrant.plugin("2", :command)
|
||||
def self.synopsis
|
||||
"Commands to manage boxes on Vagrant Cloud"
|
||||
end
|
||||
|
||||
def initialize(argv, env)
|
||||
super
|
||||
|
||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||
@subcommands = Vagrant::Registry.new
|
||||
@subcommands.register(:create) do
|
||||
require File.expand_path("../create", __FILE__)
|
||||
Command::Create
|
||||
end
|
||||
@subcommands.register(:delete) do
|
||||
require File.expand_path("../delete", __FILE__)
|
||||
Command::Delete
|
||||
end
|
||||
@subcommands.register(:show) do
|
||||
require File.expand_path("../show", __FILE__)
|
||||
Command::Show
|
||||
end
|
||||
@subcommands.register(:update) do
|
||||
require File.expand_path("../update", __FILE__)
|
||||
Command::Update
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
if @main_args.include?("-h") || @main_args.include?("--help")
|
||||
# Print the help for all the box commands.
|
||||
return help
|
||||
end
|
||||
|
||||
# If we reached this far then we must have a subcommand. If not,
|
||||
# then we also just print the help and exit.
|
||||
command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
|
||||
return help if !command_class || !@sub_command
|
||||
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
||||
|
||||
# Initialize and execute the command class
|
||||
command_class.new(@sub_args, @env).execute
|
||||
end
|
||||
|
||||
# Prints the help out for this command
|
||||
def help
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: vagrant cloud box <subcommand> [<args>]"
|
||||
opts.separator ""
|
||||
opts.separator "Commands to manage boxes on Vagrant Cloud"
|
||||
opts.separator ""
|
||||
opts.separator "Available subcommands:"
|
||||
|
||||
# Add the available subcommands as separators in order to print them
|
||||
# out as well.
|
||||
keys = []
|
||||
@subcommands.each { |key, value| keys << key.to_s }
|
||||
|
||||
keys.sort.each do |key|
|
||||
opts.separator " #{key}"
|
||||
end
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "For help on any individual subcommand run `vagrant cloud box <subcommand> -h`"
|
||||
end
|
||||
|
||||
@env.ui.info(opts.help, prefix: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module BoxCommand
|
||||
module Command
|
||||
class Show < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud box show [options] organization/box-name"
|
||||
o.separator ""
|
||||
o.separator "Displays a boxes attributes on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |u|
|
||||
options[:username] = u
|
||||
end
|
||||
o.on("--versions VERSION", String, "Display box information for a specific version") do |v|
|
||||
options[:version] = v
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
box = argv.first.split('/')
|
||||
|
||||
show_box(box[0], box[1], options, @client.token)
|
||||
end
|
||||
|
||||
def show_box(org, box_name, options, access_token)
|
||||
username = options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(username, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
|
||||
begin
|
||||
success = box.read(org, box_name)
|
||||
|
||||
if options[:version]
|
||||
# show *this* version only
|
||||
results = success["versions"].select{ |v| v if v["version"] == options[:version] }.first
|
||||
if !results
|
||||
@env.ui.warn(I18n.t("cloud_command.box.show_filter_empty", version: options[:version], org: org,box_name:box_name))
|
||||
return 0
|
||||
end
|
||||
else
|
||||
results = success
|
||||
end
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(results.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.box.show_fail", org: org,box_name:box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,71 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module BoxCommand
|
||||
module Command
|
||||
class Update < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud box update [options] organization/box-name"
|
||||
o.separator ""
|
||||
o.separator "Updates a box entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
|
||||
o.on("-d", "--description DESCRIPTION", "Longer desscription of the box") do |d|
|
||||
options[:description] = d
|
||||
end
|
||||
o.on("-u", "--username", "The username of the organization that will own the box") do |u|
|
||||
options[:username] = u
|
||||
end
|
||||
o.on("-s", "--short-description DESCRIPTION", "Short description of the box") do |s|
|
||||
options[:short_description] = s
|
||||
end
|
||||
o.on("-p", "--private", "Makes box private") do |p|
|
||||
options[:private] = p
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2 || options.length == 0
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
box = argv.first.split('/')
|
||||
|
||||
update_box(box[0], box[1], options, @client.token)
|
||||
end
|
||||
|
||||
def update_box(org, box_name, options, access_token)
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(options[:username], access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
|
||||
options[:organization] = org
|
||||
options[:name] = box_name
|
||||
begin
|
||||
success = box.update(options)
|
||||
@env.ui.success(I18n.t("cloud_command.box.update_success", org: org, box_name: box_name))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.box.update_fail", org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,258 @@
|
|||
require "rest_client"
|
||||
require "vagrant_cloud"
|
||||
require "vagrant/util/downloader"
|
||||
require "vagrant/util/presence"
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/errors")
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
class Client
|
||||
######################################################################
|
||||
# Class that deals with managing users 'local' token for Vagrant Cloud
|
||||
######################################################################
|
||||
APP = "app".freeze
|
||||
|
||||
include Vagrant::Util::Presence
|
||||
|
||||
attr_accessor :username_or_email
|
||||
attr_accessor :password
|
||||
attr_reader :two_factor_default_delivery_method
|
||||
attr_reader :two_factor_delivery_methods
|
||||
|
||||
# Initializes a login client with the given Vagrant::Environment.
|
||||
#
|
||||
# @param [Vagrant::Environment] env
|
||||
def initialize(env)
|
||||
@logger = Log4r::Logger.new("vagrant::cloud::client")
|
||||
@env = env
|
||||
end
|
||||
|
||||
# Removes the token, effectively logging the user out.
|
||||
def clear_token
|
||||
@logger.info("Clearing token")
|
||||
token_path.delete if token_path.file?
|
||||
end
|
||||
|
||||
# Checks if the user is logged in by verifying their authentication
|
||||
# token.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def logged_in?
|
||||
token = self.token
|
||||
return false if !token
|
||||
|
||||
with_error_handling do
|
||||
url = "#{Vagrant.server_url}/api/v1/authenticate" +
|
||||
"?access_token=#{token}"
|
||||
RestClient.get(url, content_type: :json)
|
||||
true
|
||||
end
|
||||
rescue Errors::Unauthorized
|
||||
false
|
||||
end
|
||||
|
||||
# Login logs a user in and returns the token for that user. The token
|
||||
# is _not_ stored unless {#store_token} is called.
|
||||
#
|
||||
# @param [String] description
|
||||
# @param [String] code
|
||||
# @return [String] token The access token, or nil if auth failed.
|
||||
def login(description: nil, code: nil)
|
||||
@logger.info("Logging in '#{username_or_email}'")
|
||||
|
||||
response = post(
|
||||
"/api/v1/authenticate", {
|
||||
user: {
|
||||
login: username_or_email,
|
||||
password: password
|
||||
},
|
||||
token: {
|
||||
description: description
|
||||
},
|
||||
two_factor: {
|
||||
code: code
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
response["token"]
|
||||
end
|
||||
|
||||
# Requests a 2FA code
|
||||
# @param [String] delivery_method
|
||||
def request_code(delivery_method)
|
||||
@env.ui.warn("Requesting 2FA code via #{delivery_method.upcase}...")
|
||||
|
||||
response = post(
|
||||
"/api/v1/two-factor/request-code", {
|
||||
user: {
|
||||
login: username_or_email,
|
||||
password: password
|
||||
},
|
||||
two_factor: {
|
||||
delivery_method: delivery_method.downcase
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
two_factor = response['two_factor']
|
||||
obfuscated_destination = two_factor['obfuscated_destination']
|
||||
|
||||
@env.ui.success("2FA code sent to #{obfuscated_destination}.")
|
||||
end
|
||||
|
||||
# Issues a post to a Vagrant Cloud path with the given payload.
|
||||
# @param [String] path
|
||||
# @param [Hash] payload
|
||||
# @return [Hash] response data
|
||||
def post(path, payload)
|
||||
with_error_handling do
|
||||
url = File.join(Vagrant.server_url, path)
|
||||
|
||||
proxy = nil
|
||||
proxy ||= ENV["HTTPS_PROXY"] || ENV["https_proxy"]
|
||||
proxy ||= ENV["HTTP_PROXY"] || ENV["http_proxy"]
|
||||
RestClient.proxy = proxy
|
||||
|
||||
response = RestClient::Request.execute(
|
||||
method: :post,
|
||||
url: url,
|
||||
payload: JSON.dump(payload),
|
||||
proxy: proxy,
|
||||
headers: {
|
||||
accept: :json,
|
||||
content_type: :json,
|
||||
user_agent: Vagrant::Util::Downloader::USER_AGENT,
|
||||
},
|
||||
)
|
||||
|
||||
JSON.load(response.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
# Stores the given token locally, removing any previous tokens.
|
||||
#
|
||||
# @param [String] token
|
||||
def store_token(token)
|
||||
@logger.info("Storing token in #{token_path}")
|
||||
|
||||
token_path.open("w") do |f|
|
||||
f.write(token)
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Reads the access token if there is one. This will first read the
|
||||
# `VAGRANT_CLOUD_TOKEN` environment variable and then fallback to the stored
|
||||
# access token on disk.
|
||||
#
|
||||
# @return [String]
|
||||
def token
|
||||
if present?(ENV["VAGRANT_CLOUD_TOKEN"]) && token_path.exist?
|
||||
@env.ui.warn <<-EOH.strip
|
||||
Vagrant detected both the VAGRANT_CLOUD_TOKEN environment variable and a Vagrant login
|
||||
token are present on this system. The VAGRANT_CLOUD_TOKEN environment variable takes
|
||||
precedence over the locally stored token. To remove this error, either unset
|
||||
the VAGRANT_CLOUD_TOKEN environment variable or remove the login token stored on disk:
|
||||
|
||||
~/.vagrant.d/data/vagrant_login_token
|
||||
|
||||
EOH
|
||||
end
|
||||
|
||||
if present?(ENV["VAGRANT_CLOUD_TOKEN"])
|
||||
@logger.debug("Using authentication token from environment variable")
|
||||
return ENV["VAGRANT_CLOUD_TOKEN"]
|
||||
end
|
||||
|
||||
if token_path.exist?
|
||||
@logger.debug("Using authentication token from disk at #{token_path}")
|
||||
return token_path.read.strip
|
||||
end
|
||||
|
||||
if present?(ENV["ATLAS_TOKEN"])
|
||||
@logger.warn("ATLAS_TOKEN detected within environment. Using ATLAS_TOKEN in place of VAGRANT_CLOUD_TOKEN.")
|
||||
return ENV["ATLAS_TOKEN"]
|
||||
end
|
||||
|
||||
@logger.debug("No authentication token in environment or #{token_path}")
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def with_error_handling(&block)
|
||||
yield
|
||||
rescue RestClient::Unauthorized
|
||||
@logger.debug("Unauthorized!")
|
||||
raise Errors::Unauthorized
|
||||
rescue RestClient::BadRequest => e
|
||||
@logger.debug("Bad request:")
|
||||
@logger.debug(e.message)
|
||||
@logger.debug(e.backtrace.join("\n"))
|
||||
parsed_response = JSON.parse(e.response)
|
||||
errors = parsed_response["errors"].join("\n")
|
||||
raise Errors::ServerError, errors: errors
|
||||
rescue RestClient::NotAcceptable => e
|
||||
@logger.debug("Got unacceptable response:")
|
||||
@logger.debug(e.message)
|
||||
@logger.debug(e.backtrace.join("\n"))
|
||||
|
||||
parsed_response = JSON.parse(e.response)
|
||||
|
||||
if two_factor = parsed_response['two_factor']
|
||||
store_two_factor_information two_factor
|
||||
|
||||
if two_factor_default_delivery_method != APP
|
||||
request_code two_factor_default_delivery_method
|
||||
end
|
||||
|
||||
raise Errors::TwoFactorRequired
|
||||
end
|
||||
|
||||
begin
|
||||
errors = parsed_response["errors"].join("\n")
|
||||
raise Errors::ServerError, errors: errors
|
||||
rescue JSON::ParserError; end
|
||||
|
||||
raise "An unexpected error occurred: #{e.inspect}"
|
||||
rescue SocketError
|
||||
@logger.info("Socket error")
|
||||
raise Errors::ServerUnreachable, url: Vagrant.server_url.to_s
|
||||
end
|
||||
|
||||
def token_path
|
||||
@env.data_dir.join("vagrant_login_token")
|
||||
end
|
||||
|
||||
def store_two_factor_information(two_factor)
|
||||
@two_factor_default_delivery_method =
|
||||
two_factor['default_delivery_method']
|
||||
|
||||
@two_factor_delivery_methods =
|
||||
two_factor['delivery_methods']
|
||||
|
||||
@env.ui.warn "2FA is enabled for your account."
|
||||
if two_factor_default_delivery_method == APP
|
||||
@env.ui.info "Enter the code from your authenticator."
|
||||
else
|
||||
@env.ui.info "Default method is " \
|
||||
"'#{two_factor_default_delivery_method}'."
|
||||
end
|
||||
|
||||
other_delivery_methods =
|
||||
two_factor_delivery_methods - [APP]
|
||||
|
||||
if other_delivery_methods.any?
|
||||
other_delivery_methods_sentence = other_delivery_methods
|
||||
.map { |word| "'#{word}'" }
|
||||
.join(' or ')
|
||||
@env.ui.info "You can also type #{other_delivery_methods_sentence} " \
|
||||
"to request a new code."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module Errors
|
||||
class Error < Vagrant::Errors::VagrantError
|
||||
error_namespace("cloud_command.errors")
|
||||
end
|
||||
|
||||
class ServerError < Error
|
||||
error_key(:server_error)
|
||||
end
|
||||
|
||||
class ServerUnreachable < Error
|
||||
error_key(:server_unreachable)
|
||||
end
|
||||
|
||||
class Unauthorized < Error
|
||||
error_key(:unauthorized)
|
||||
end
|
||||
|
||||
class TwoFactorRequired < Error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,52 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module Command
|
||||
class List < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud list [options] organization"
|
||||
o.separator ""
|
||||
o.separator "Search for boxes managed by a specific user"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-j", "--json", "Formats results in JSON") do |j|
|
||||
options[:check] = j
|
||||
end
|
||||
o.on("-l", "--limit", Integer, "Max number of search results (default is 25)") do |l|
|
||||
options[:check] = l
|
||||
end
|
||||
o.on("-p", "--provider", "Comma separated list of providers to filter search on. Defaults to all.") do |p|
|
||||
options[:check] = p
|
||||
end
|
||||
o.on("-s", "--sort-by", "Column to sort list (created, downloads, updated)") do |s|
|
||||
options[:check] = s
|
||||
end
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
# TODO: This endpoint is not implemented yet
|
||||
|
||||
0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,138 @@
|
|||
en:
|
||||
cloud_command:
|
||||
publish:
|
||||
box_create:
|
||||
Creating a box entry...
|
||||
version_create:
|
||||
Creating a version entry...
|
||||
provider_create:
|
||||
Creating a provider entry...
|
||||
upload_provider:
|
||||
Uploading provider with file %{file}
|
||||
release:
|
||||
Releasing box...
|
||||
complete:
|
||||
Complete! Published %{org}/%{box_name}
|
||||
continue: |-
|
||||
Do you wish to continue? [y/N]
|
||||
box:
|
||||
show_filter_empty: |-
|
||||
No version matched %{version} for %{org}/%{box_name}
|
||||
create_success: |-
|
||||
Created box %{org}/%{box_name}
|
||||
delete_success: |-
|
||||
Deleted box %{org}/%{box_name}
|
||||
delete_warn: |-
|
||||
This will completely remove %{box} from Vagrant Cloud. This cannot be undone.
|
||||
update_success: |-
|
||||
Updated box %{org}/%{box_name}
|
||||
search:
|
||||
no_results: |-
|
||||
No results found for %{query}
|
||||
upload:
|
||||
no_url: |-
|
||||
No URL was provided to upload the provider
|
||||
You will need to run the `vagrant cloud provider upload` command to provide a box
|
||||
provider:
|
||||
upload: |-
|
||||
Uploading provider %{provider_file} ...
|
||||
upload_success: |-
|
||||
Uploaded provider %{provider} on %{org}/%{box_name} for version %{version}
|
||||
delete_warn: |-
|
||||
This will completely remove provider %{provider} on version %{version} from %{box} on Vagrant Cloud. This cannot be undone.
|
||||
create_success: |-
|
||||
Created provider %{provider} on %{org}/%{box_name} for version %{version}
|
||||
delete_success: |-
|
||||
Deleted provider %{provider} on %{org}/%{box_name} for version %{version}
|
||||
update_success: |-
|
||||
Updated provider %{provider} on %{org}/%{box_name} for version %{version}
|
||||
version:
|
||||
create_success: |-
|
||||
Created version %{version} on %{org}/%{box_name} for version %{version}
|
||||
delete_success: |-
|
||||
Deleted version %{version} on %{org}/%{box_name}
|
||||
release_success: |-
|
||||
Released version %{version} on %{org}/%{box_name}
|
||||
revoke_success: |-
|
||||
Revoked version %{version} on %{org}/%{box_name}
|
||||
update_success: |-
|
||||
Updated version %{version} on %{org}/%{box_name}
|
||||
revoke_warn: |-
|
||||
This will revoke version %{version} from %{box} from Vagrant Cloud. This cannot be undone.
|
||||
release_warn: |-
|
||||
This will release version %{version} from %{box} to Vagrant Cloud and be available to download.
|
||||
delete_warn: |-
|
||||
This will completely remove version %{version} from %{box} from Vagrant Cloud. This cannot be undone.
|
||||
errors:
|
||||
search:
|
||||
fail: |-
|
||||
Could not complete search request
|
||||
publish:
|
||||
fail: |-
|
||||
Failed to create box %{org}/%{box_name}
|
||||
box:
|
||||
create_fail: |-
|
||||
Failed to create box %{org}/%{box_name}
|
||||
delete_fail: |-
|
||||
Failed to delete box %{org}/%{box_name}
|
||||
show_fail: |-
|
||||
Could not get information about box %{org}/%{box_name}
|
||||
update_fail: |-
|
||||
Failed to update box %{org}/%{box_name}
|
||||
whoami:
|
||||
read_error: |-
|
||||
Failed to read organization %{org}
|
||||
provider:
|
||||
create_fail: |-
|
||||
Failed to create provider %{provider} on box %{org}/%{box_name} for version %{version}
|
||||
update_fail: |-
|
||||
Failed to update provider %{provider} on box %{org}/%{box_name} for version %{version}
|
||||
delete_fail: |-
|
||||
Failed to delete provider %{provider} on box %{org}/%{box_name} for version %{version}
|
||||
upload_fail: |-
|
||||
Failed to upload provider %{provider} on box %{org}/%{box_name} for version %{version}
|
||||
version:
|
||||
create_fail: |-
|
||||
Failed to create version %{version} on box %{org}/%{box_name}
|
||||
delete_fail: |-
|
||||
Failed to delete version %{version} on box %{org}/%{box_name}
|
||||
release_fail: |-
|
||||
Failed to release version %{version} on box %{org}/%{box_name}
|
||||
revoke_fail: |-
|
||||
Failed to revoke version %{version} on box %{org}/%{box_name}
|
||||
update_fail: |-
|
||||
Failed to update version %{version} on box %{org}/%{box_name}
|
||||
server_error: |-
|
||||
The Vagrant Cloud server responded with a not-OK response:
|
||||
|
||||
%{errors}
|
||||
server_unreachable: |-
|
||||
The Vagrant Cloud server is not currently accepting connections. Please check
|
||||
your network connection and try again later.
|
||||
|
||||
unauthorized: |-
|
||||
Invalid username or password. Please try again.
|
||||
|
||||
check_logged_in: |-
|
||||
You are already logged in.
|
||||
check_not_logged_in: |-
|
||||
You are not currently logged in. Please run `vagrant login` and provide
|
||||
your login information to authenticate.
|
||||
command_header: |-
|
||||
In a moment we will ask for your username and password to HashiCorp's
|
||||
Vagrant Cloud. After authenticating, we will store an access token locally on
|
||||
disk. Your login details will be transmitted over a secure connection, and
|
||||
are never stored on disk locally.
|
||||
|
||||
If you do not have an Vagrant Cloud account, sign up at
|
||||
https://www.vagrantcloud.com
|
||||
invalid_login: |-
|
||||
Invalid username or password. Please try again.
|
||||
invalid_token: |-
|
||||
Invalid token. Please try again.
|
||||
logged_in: |-
|
||||
You are now logged in.
|
||||
logged_out: |-
|
||||
You are logged out.
|
||||
token_saved: |-
|
||||
The token was successfully saved.
|
|
@ -0,0 +1,30 @@
|
|||
require "vagrant"
|
||||
require 'vagrant_cloud'
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/util")
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/client/client")
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "vagrant-cloud"
|
||||
description <<-DESC
|
||||
Provides the cloud command and internal API access to Vagrant Cloud.
|
||||
DESC
|
||||
|
||||
command(:cloud) do
|
||||
require_relative "root"
|
||||
init!
|
||||
Command::Root
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.init!
|
||||
return if defined?(@_init)
|
||||
I18n.load_path << File.expand_path("../locales/en.yml", __FILE__)
|
||||
I18n.reload!
|
||||
@_init = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,72 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module ProviderCommand
|
||||
module Command
|
||||
class Create < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud provider create [options] organization/box-name provider-name version [url]"
|
||||
o.separator ""
|
||||
o.separator "Creates a provider entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 4
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
provider_name = argv[1]
|
||||
version = argv[2]
|
||||
url = argv[3]
|
||||
|
||||
upload_provider(org, box_name, provider_name, version, url, @client.token, options)
|
||||
end
|
||||
|
||||
def upload_provider(org, box_name, provider_name, version, url, access_token, options)
|
||||
if !url
|
||||
@env.ui.warn(I18n.t("cloud_command.upload.no_url"))
|
||||
end
|
||||
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
cloud_version = VagrantCloud::Version.new(box, version, nil, nil, access_token)
|
||||
provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, url, org, box_name, access_token)
|
||||
|
||||
begin
|
||||
success = provider.create_provider
|
||||
@env.ui.success(I18n.t("cloud_command.provider.create_success", provider:provider_name, org: org, box_name: box_name, version: version))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.provider.create_fail", provider:provider_name, org: org, box_name: box_name, version: version))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module ProviderCommand
|
||||
module Command
|
||||
class Delete < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud provider delete [options] organization/box-name provider-name version"
|
||||
o.separator ""
|
||||
o.separator "Deletes a provider entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 3
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
provider_name = argv[1]
|
||||
version = argv[2]
|
||||
|
||||
@env.ui.warn(I18n.t("cloud_command.provider.delete_warn", provider: provider_name, version:version, box: argv.first))
|
||||
continue = @env.ui.ask(I18n.t("cloud_command.continue"))
|
||||
return 1 if continue.downcase != "y"
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
delete_provider(org, box_name, provider_name, version, @client.token, options)
|
||||
end
|
||||
|
||||
def delete_provider(org, box_name, provider_name, version, access_token, options)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
cloud_version = VagrantCloud::Version.new(box, version, nil, nil, access_token)
|
||||
provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, nil, nil, nil, access_token)
|
||||
|
||||
begin
|
||||
success = provider.delete
|
||||
@env.ui.error(I18n.t("cloud_command.provider.delete_success", provider: provider_name, org: org, box_name: box_name, version: version))
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.provider.delete_fail", provider: provider_name, org: org, box_name: box_name, version: version))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module ProviderCommand
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "vagrant cloud box"
|
||||
description <<-DESC
|
||||
Provider CRUD commands for Vagrant Cloud
|
||||
DESC
|
||||
|
||||
command(:provider) do
|
||||
require_relative "root"
|
||||
Command::Root
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module ProviderCommand
|
||||
module Command
|
||||
class Root < Vagrant.plugin("2", :command)
|
||||
def self.synopsis
|
||||
"Provider commands"
|
||||
end
|
||||
|
||||
def initialize(argv, env)
|
||||
super
|
||||
|
||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||
@subcommands = Vagrant::Registry.new
|
||||
@subcommands.register(:create) do
|
||||
require File.expand_path("../create", __FILE__)
|
||||
Command::Create
|
||||
end
|
||||
@subcommands.register(:delete) do
|
||||
require File.expand_path("../delete", __FILE__)
|
||||
Command::Delete
|
||||
end
|
||||
@subcommands.register(:update) do
|
||||
require File.expand_path("../update", __FILE__)
|
||||
Command::Update
|
||||
end
|
||||
@subcommands.register(:upload) do
|
||||
require File.expand_path("../upload", __FILE__)
|
||||
Command::Upload
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
if @main_args.include?("-h") || @main_args.include?("--help")
|
||||
# Print the help for all the provider commands.
|
||||
return help
|
||||
end
|
||||
|
||||
# If we reached this far then we must have a subcommand. If not,
|
||||
# then we also just print the help and exit.
|
||||
command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
|
||||
return help if !command_class || !@sub_command
|
||||
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
||||
|
||||
# Initialize and execute the command class
|
||||
command_class.new(@sub_args, @env).execute
|
||||
end
|
||||
|
||||
# Prints the help out for this command
|
||||
def help
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: vagrant cloud provider <subcommand> [<args>]"
|
||||
opts.separator ""
|
||||
opts.separator "For various provider actions with Vagrant Cloud"
|
||||
opts.separator ""
|
||||
opts.separator "Available subcommands:"
|
||||
|
||||
# Add the available subcommands as separators in order to print them
|
||||
# out as well.
|
||||
keys = []
|
||||
@subcommands.each { |key, value| keys << key.to_s }
|
||||
|
||||
keys.sort.each do |key|
|
||||
opts.separator " #{key}"
|
||||
end
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "For help on any individual subcommand run `vagrant cloud provider <subcommand> -h`"
|
||||
end
|
||||
|
||||
@env.ui.info(opts.help, prefix: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,72 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module ProviderCommand
|
||||
module Command
|
||||
class Update < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud provider update [options] organization/box-name provider-name version url"
|
||||
o.separator ""
|
||||
o.separator "Updates a provider entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 4
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
provider_name = argv[1]
|
||||
version = argv[2]
|
||||
url = argv[3]
|
||||
|
||||
update_provider(org, box_name, provider_name, version, url, @client.token, options)
|
||||
end
|
||||
|
||||
def update_provider(org, box_name, provider_name, version, url, access_token, options)
|
||||
if !url
|
||||
@env.ui.warn(I18n.t("cloud_command.upload.no_url"))
|
||||
end
|
||||
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
cloud_version = VagrantCloud::Version.new(box, version, nil, nil, access_token)
|
||||
provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, url, org, box_name, access_token)
|
||||
|
||||
begin
|
||||
success = provider.update
|
||||
@env.ui.success(I18n.t("cloud_command.provider.update_success", provider:provider_name, org: org, box_name: box_name, version: version))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.provider.update_fail", provider:provider_name, org: org, box_name: box_name, version: version))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module ProviderCommand
|
||||
module Command
|
||||
class Upload < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud provider upload [options] organization/box-name provider-name version box-file"
|
||||
o.separator ""
|
||||
o.separator "Uploads a box file to Vagrant Cloud for a specific provider"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 4
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
provider_name = argv[1]
|
||||
version = argv[2]
|
||||
file = argv[3]
|
||||
|
||||
upload_provider(org, box_name, provider_name, version, file, @client.token, options)
|
||||
end
|
||||
|
||||
def upload_provider(org, box_name, provider_name, version, file, access_token, options)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
cloud_version = VagrantCloud::Version.new(box, version, nil, nil, access_token)
|
||||
provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, nil, org, box_name, access_token)
|
||||
|
||||
begin
|
||||
@env.ui.info(I18n.t("cloud_command.provider.upload", provider_file: file))
|
||||
success = provider.upload_file(file)
|
||||
@env.ui.success(I18n.t("cloud_command.provider.upload_success", provider: provider_name, org: org, box_name: box_name, version: version))
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.provider.upload_fail", provider: provider_name, org: org, box_name: box_name, version: version))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,119 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module Command
|
||||
class Publish < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud publish [options] organization/box-name version provider-name [provider-file]"
|
||||
o.separator ""
|
||||
o.separator "A Start-To-Finish command for creating and releasing a new Vagrant Box on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("--box-version VERSION", String, "Version of box to create") do |v|
|
||||
options[:box_version] = v
|
||||
end
|
||||
o.on("--url", String, "Valid remote URL to download this provider") do |u|
|
||||
options[:url] = u
|
||||
end
|
||||
o.on("-d", "--description DESCRIPTION", String, "Longer description of box") do |d|
|
||||
options[:description] = d
|
||||
end
|
||||
o.on("--version-description DESCRIPTION", String, "Description of the version to create") do |v|
|
||||
options[:version_description] = v
|
||||
end
|
||||
o.on("-f", "--force", "Disables confirmation to create or update box") do |f|
|
||||
options[:force] = f
|
||||
end
|
||||
o.on("-p", "--private", "Makes box private") do |p|
|
||||
options[:private] = p
|
||||
end
|
||||
o.on("-r", "--release", "Releases box") do |p|
|
||||
options[:release] = p
|
||||
end
|
||||
o.on("-s", "--short-description DESCRIPTION", String, "Short description of the box") do |s|
|
||||
options[:short_description] = s
|
||||
end
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 4 || argv.length < 4
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
version = argv[1]
|
||||
provider_name = argv[2]
|
||||
box_file = argv[3]
|
||||
publish_box(org, box_name, version, provider_name, box_file, options, @client.token)
|
||||
end
|
||||
|
||||
def publish_box(org, box_name, version, provider_name, box_file, options, access_token)
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
|
||||
@env.ui.warn("You are about to create a box on Vagrant Cloud with the following options:\n")
|
||||
box_opts = " #{org}/#{box_name} (#{version}) for #{provider_name}\n"
|
||||
box_opts << " Private: true\n" if options[:private]
|
||||
box_opts << " Automatic Release: true\n" if options[:release]
|
||||
box_opts << " Remote Box file: true\n" if options[:url]
|
||||
box_opts << " Box Description: #{options[:description]}\n" if options[:description]
|
||||
box_opts << " Box Short Description: #{options[:short_description]}\n" if options[:short_description]
|
||||
box_opts << " Version Description: #{options[:version_description]}\n" if options[:version_description]
|
||||
|
||||
@env.ui.info(box_opts)
|
||||
|
||||
if !options[:force]
|
||||
continue = @env.ui.ask(I18n.t("cloud_command.continue"))
|
||||
return 1 if continue.downcase != "y"
|
||||
end
|
||||
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, options[:short_description], options[:description], access_token)
|
||||
cloud_version = VagrantCloud::Version.new(box, version, nil, options[:version_description], access_token)
|
||||
provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, options[:url], org, box_name, access_token)
|
||||
|
||||
begin
|
||||
@env.ui.info(I18n.t("cloud_command.publish.box_create"))
|
||||
box.create
|
||||
@env.ui.info(I18n.t("cloud_command.publish.version_create"))
|
||||
cloud_version.create_version
|
||||
@env.ui.info(I18n.t("cloud_command.publish.provider_create"))
|
||||
provider.create_provider
|
||||
if !options[:url]
|
||||
@env.ui.info(I18n.t("cloud_command.publish.upload_provider", file: box_file))
|
||||
provider.upload_file(box_file)
|
||||
end
|
||||
if options[:release]
|
||||
@env.ui.info(I18n.t("cloud_command.publish.release"))
|
||||
cloud_version.release
|
||||
end
|
||||
@env.ui.success(I18n.t("cloud_command.publish.complete", org: org, box_name: box_name))
|
||||
success = box.read(org, box_name)
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.publish.fail", org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,104 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module Command
|
||||
class Root < Vagrant.plugin("2", :command)
|
||||
def self.synopsis
|
||||
"manages everything related to Vagrant Cloud"
|
||||
end
|
||||
|
||||
def initialize(argv, env)
|
||||
super
|
||||
|
||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||
@subcommands = Vagrant::Registry.new
|
||||
@subcommand_helptext = {}
|
||||
|
||||
@subcommands.register(:auth) do
|
||||
require File.expand_path("../auth/root", __FILE__)
|
||||
AuthCommand::Command::Root
|
||||
end
|
||||
@subcommand_helptext[:auth] = "For various authorization operations on Vagrant Cloud"
|
||||
|
||||
@subcommands.register(:box) do
|
||||
require File.expand_path("../box/root", __FILE__)
|
||||
BoxCommand::Command::Root
|
||||
end
|
||||
@subcommand_helptext[:box] = "For managing a Vagrant box entry on Vagrant Cloud"
|
||||
|
||||
# TODO: Uncomment this when API endpoint exists
|
||||
#@subcommands.register(:list) do
|
||||
# require File.expand_path("../list", __FILE__)
|
||||
# List
|
||||
#end
|
||||
#@subcommand_helptext[:list] = "Displays a list of Vagrant boxes that the current user manages"
|
||||
|
||||
@subcommands.register(:search) do
|
||||
require File.expand_path("../search", __FILE__)
|
||||
Search
|
||||
end
|
||||
@subcommand_helptext[:search] = "Search Vagrant Cloud for available boxes"
|
||||
|
||||
@subcommands.register(:provider) do
|
||||
require File.expand_path("../provider/root", __FILE__)
|
||||
ProviderCommand::Command::Root
|
||||
end
|
||||
@subcommand_helptext[:provider] = "For managing a Vagrant box's provider options"
|
||||
|
||||
@subcommands.register(:publish) do
|
||||
require File.expand_path("../publish", __FILE__)
|
||||
Publish
|
||||
end
|
||||
@subcommand_helptext[:publish] = "A start-to-finish solution for creating or updating a new box on Vagrant Cloud"
|
||||
|
||||
@subcommands.register(:version) do
|
||||
require File.expand_path("../version/root", __FILE__)
|
||||
VersionCommand::Command::Root
|
||||
end
|
||||
@subcommand_helptext[:version] = "For managing a Vagrant box's versions"
|
||||
end
|
||||
|
||||
def execute
|
||||
if @main_args.include?("-h") || @main_args.include?("--help")
|
||||
# Print the help for all the box commands.
|
||||
return help
|
||||
end
|
||||
|
||||
# If we reached this far then we must have a subcommand. If not,
|
||||
# then we also just print the help and exit.
|
||||
command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
|
||||
return help if !command_class || !@sub_command
|
||||
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
||||
|
||||
# Initialize and execute the command class
|
||||
command_class.new(@sub_args, @env).execute
|
||||
end
|
||||
|
||||
# Prints the help out for this command
|
||||
def help
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: vagrant cloud <subcommand> [<args>]"
|
||||
opts.separator ""
|
||||
opts.separator "The cloud command can be used for taking actions against"
|
||||
opts.separator "Vagrant Cloud like searching or uploading a Vagrant Box"
|
||||
opts.separator ""
|
||||
opts.separator "Available subcommands:"
|
||||
|
||||
# Add the available subcommands as separators in order to print them
|
||||
# out as well.
|
||||
keys = []
|
||||
@subcommands.each { |key, value| keys << key.to_s }
|
||||
|
||||
keys.sort.each do |key|
|
||||
opts.separator " #{key.ljust(15)} #{@subcommand_helptext[key.to_sym]}"
|
||||
end
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "For help on any individual subcommand run `vagrant cloud <subcommand> -h`"
|
||||
end
|
||||
|
||||
@env.ui.info(opts.help, prefix: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,82 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module Command
|
||||
class Search < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud search [options] query"
|
||||
o.separator ""
|
||||
o.separator "Search for a box on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-j", "--json", "Formats results in JSON") do |j|
|
||||
options[:json] = j
|
||||
end
|
||||
o.on("-p", "--page PAGE", Integer, "The page to display Default: 1") do |j|
|
||||
options[:page] = j
|
||||
end
|
||||
o.on("-s", "--short", "Shows a simple list of box names") do |s|
|
||||
options[:short] = s
|
||||
end
|
||||
o.on("-o", "--order ORDER", String, "Order to display results ('desc' or 'asc') Default: 'desc'") do |o|
|
||||
options[:order] = o
|
||||
end
|
||||
o.on("-l", "--limit LIMIT", Integer, "Max number of search results Default: 25") do |l|
|
||||
options[:limit] = l
|
||||
end
|
||||
o.on("-p", "--provider PROVIDER", String, "Filter search results to a single provider. Defaults to all.") do |p|
|
||||
options[:provider] = p
|
||||
end
|
||||
o.on("--sort-by SORT", "Field to sort results on (created, downloads, updated) Default: downloads") do |s|
|
||||
options[:sort] = s
|
||||
end
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
query = argv.first
|
||||
|
||||
options[:limit] = 25 if !options[:limit]
|
||||
|
||||
search(query, options, @client.token)
|
||||
end
|
||||
|
||||
def search(query, options, access_token)
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
search = VagrantCloud::Search.new(access_token, server_url)
|
||||
|
||||
begin
|
||||
search_results = search.search(query, options[:provider], options[:sort], options[:order], options[:limit], options[:page])
|
||||
if !search_results["boxes"].empty?
|
||||
VagrantPlugins::CloudCommand::Util.format_search_results(search_results["boxes"], options[:short], options[:json], @env)
|
||||
else
|
||||
@env.ui.warn(I18n.t("cloud_command.search.no_results", query: query))
|
||||
end
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.search.fail"))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,199 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
class Util
|
||||
class << self
|
||||
def account?(username, access_token, vagrant_cloud_server)
|
||||
if !defined?(@_account)
|
||||
@_account = VagrantCloud::Account.new(username, access_token, vagrant_cloud_server)
|
||||
end
|
||||
@_account
|
||||
end
|
||||
|
||||
def api_server_url
|
||||
if Vagrant.server_url == Vagrant::DEFAULT_SERVER_URL
|
||||
return "#{Vagrant.server_url}/api/v1"
|
||||
else
|
||||
return Vagrant.server_url
|
||||
end
|
||||
end
|
||||
|
||||
def client_login(env, options)
|
||||
if !defined?(@_client)
|
||||
@_client = Client.new(env)
|
||||
return @_client if @_client.logged_in?
|
||||
|
||||
# Let the user know what is going on.
|
||||
env.ui.output(I18n.t("cloud_command.command_header") + "\n")
|
||||
|
||||
# If it is a private cloud installation, show that
|
||||
if Vagrant.server_url != Vagrant::DEFAULT_SERVER_URL
|
||||
env.ui.output("Vagrant Cloud URL: #{Vagrant.server_url}")
|
||||
end
|
||||
|
||||
# Ask for the username
|
||||
if @_client.username_or_email
|
||||
env.ui.output("Vagrant Cloud username or email: #{@_client.username_or_email}")
|
||||
end
|
||||
until @_client.username_or_email
|
||||
@_client.username_or_email = env.ui.ask("Vagrant Cloud username or email: ")
|
||||
end
|
||||
|
||||
until @_client.password
|
||||
@_client.password = env.ui.ask("Password (will be hidden): ", echo: false)
|
||||
end
|
||||
|
||||
if options
|
||||
description = options[:description]
|
||||
end
|
||||
description_default = "Vagrant login from #{Socket.gethostname}"
|
||||
until description
|
||||
description =
|
||||
env.ui.ask("Token description (Defaults to #{description_default.inspect}): ")
|
||||
end
|
||||
description = description_default if description.empty?
|
||||
|
||||
code = nil
|
||||
|
||||
begin
|
||||
token = @_client.login(description: description, code: code)
|
||||
rescue Errors::TwoFactorRequired
|
||||
until code
|
||||
code = env.ui.ask("2FA code: ")
|
||||
|
||||
if @_client.two_factor_delivery_methods.include?(code.downcase)
|
||||
delivery_method, code = code, nil
|
||||
@_client.request_code delivery_method
|
||||
end
|
||||
end
|
||||
|
||||
retry
|
||||
end
|
||||
|
||||
@_client.store_token(token)
|
||||
env.ui.success(I18n.t("cloud_command.logged_in"))
|
||||
@_client
|
||||
end
|
||||
@_client
|
||||
end
|
||||
|
||||
# ===================================================
|
||||
# Modified from https://stackoverflow.com/a/28685559
|
||||
# for printing arrays of hashes in formatted tables
|
||||
# ===================================================
|
||||
|
||||
# @param [Vagrant::Environment] - env
|
||||
# @param [Hash] - column_labels - A hash of key values for table labels (i.e. {:col1=>"COL1", :col2=>"COL2"})
|
||||
# @param [Array] - results - An array of hashes
|
||||
# @param [Array] - to_jrust_keys - An array of column keys that should be right justified (default is left justified for all columns)
|
||||
def print_search_table(env, column_labels, results, to_rjust_keys)
|
||||
columns = column_labels.each_with_object({}) { |(col,label),h|
|
||||
h[col] = { label: label,
|
||||
width: [results.map { |g| g[col].size }.max, label.size].max
|
||||
}}
|
||||
|
||||
write_header(env, columns)
|
||||
write_divider(env, columns)
|
||||
results.each { |h| write_line(env, columns, h,to_rjust_keys) }
|
||||
write_divider(env, columns)
|
||||
end
|
||||
|
||||
def write_header(env, columns)
|
||||
env.ui.info "| #{ columns.map { |_,g| g[:label].ljust(g[:width]) }.join(' | ') } |"
|
||||
end
|
||||
|
||||
def write_divider(env, columns)
|
||||
env.ui.info "+-#{ columns.map { |_,g| "-"*g[:width] }.join("-+-") }-+"
|
||||
end
|
||||
|
||||
def write_line(env, columns,h,to_rjust_keys)
|
||||
str = h.keys.map { |k|
|
||||
if to_rjust_keys.include?(k)
|
||||
h[k].rjust(columns[k][:width])
|
||||
else
|
||||
h[k].ljust(columns[k][:width])
|
||||
end
|
||||
}.join(" | ")
|
||||
env.ui.info "| #{str} |"
|
||||
end
|
||||
|
||||
# ===================================================
|
||||
# ===================================================
|
||||
|
||||
# Takes a "mostly" flat key=>value hash from Vagrant Cloud
|
||||
# and prints its results in a list
|
||||
#
|
||||
# @param [Hash] - results - A response hash from vagrant cloud
|
||||
# @param [Vagrant::Environment] - env
|
||||
def format_box_results(results, env)
|
||||
# TODO: remove other description fields? Maybe leave "short"?
|
||||
results.delete("description_html")
|
||||
|
||||
if results["current_version"]
|
||||
versions = results.delete("versions")
|
||||
results["providers"] = results["current_version"]["providers"]
|
||||
|
||||
results["old_versions"] = versions.map{ |v| v["version"] }[1..5].join(", ") + "..."
|
||||
end
|
||||
|
||||
|
||||
width = results.keys.map{|k| k.size}.max
|
||||
results.each do |k,v|
|
||||
if k == "versions"
|
||||
v = v.map{ |ver| ver["version"] }.join(", ")
|
||||
elsif k == "current_version"
|
||||
v = v["version"]
|
||||
elsif k == "providers"
|
||||
v = v.map{ |p| p["name"] }.join(", ")
|
||||
elsif k == "downloads"
|
||||
v = format_downloads(v.to_s)
|
||||
end
|
||||
|
||||
whitespace = width-k.size
|
||||
env.ui.info "#{k}:" + "".ljust(whitespace) + " #{v}"
|
||||
end
|
||||
end
|
||||
|
||||
# Converts a string of numbers into a formatted number
|
||||
#
|
||||
# 1234 -> 1,234
|
||||
#
|
||||
# @param [String] - download_string
|
||||
def format_downloads(download_string)
|
||||
return download_string.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
||||
end
|
||||
|
||||
|
||||
# @param [Array] search_results - Box search results from Vagrant Cloud
|
||||
# @param [String,nil] short - determines if short version will be printed
|
||||
# @param [String,nil] json - determines if json version will be printed
|
||||
# @param [Vagrant::Environment] - env
|
||||
def format_search_results(search_results, short, json, env)
|
||||
result = []
|
||||
search_results.each do |b|
|
||||
box = {}
|
||||
box = {
|
||||
name: b["tag"],
|
||||
version: b["current_version"]["version"],
|
||||
downloads: format_downloads(b["downloads"].to_s),
|
||||
providers: b["current_version"]["providers"].map{ |p| p["name"] }.join(",")
|
||||
}
|
||||
result << box
|
||||
end
|
||||
|
||||
if short
|
||||
result.map {|b| env.ui.info(b[:name])}
|
||||
elsif json
|
||||
env.ui.info(result.to_json)
|
||||
else
|
||||
column_labels = {}
|
||||
columns = result.first.keys
|
||||
columns.each do |c|
|
||||
column_labels[c] = c.to_s.upcase
|
||||
end
|
||||
print_search_table(env, column_labels, result, [:downloads])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
module Command
|
||||
class Create < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud version create [options] organization/box-name version"
|
||||
o.separator ""
|
||||
o.separator "Creates a version entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-d", "--description DESCRIPTION", String, "A description for this version") do |d|
|
||||
options[:description] = d
|
||||
end
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
version = argv[1]
|
||||
|
||||
create_version(org, box_name, version, @client.token, options)
|
||||
end
|
||||
|
||||
def create_version(org, box_name, box_version, access_token, options)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
version = VagrantCloud::Version.new(box, box_version, nil, options[:description], access_token)
|
||||
|
||||
begin
|
||||
success = version.create_version
|
||||
@env.ui.success(I18n.t("cloud_command.version.create_success", version: box_version, org: org, box_name: box_name))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.version.create_fail", version: box_version, org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
module Command
|
||||
class Delete < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud version delete [options] organization/box-name version"
|
||||
o.separator ""
|
||||
o.separator "Deletes a version entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
version = argv[1]
|
||||
|
||||
@env.ui.warn(I18n.t("cloud_command.version.delete_warn", version: version, box: argv.first))
|
||||
continue = @env.ui.ask(I18n.t("cloud_command.continue"))
|
||||
return 1 if continue.downcase != "y"
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
|
||||
delete_version(org, box_name, version, options, @client.token)
|
||||
end
|
||||
|
||||
def delete_version(org, box_name, box_version, options, access_token)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
version = VagrantCloud::Version.new(box, box_version, nil, nil, access_token)
|
||||
|
||||
begin
|
||||
success = version.delete
|
||||
@env.ui.success(I18n.t("cloud_command.version.delete_success", version: box_version, org: org, box_name: box_name))
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.version.delete_fail", version: box_version, org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "vagrant cloud version"
|
||||
description <<-DESC
|
||||
Version CRUD commands for Vagrant Cloud
|
||||
DESC
|
||||
|
||||
command(:version) do
|
||||
require_relative "root"
|
||||
Command::Root
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
module Command
|
||||
class Release < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud version release [options] organization/box-name version"
|
||||
o.separator ""
|
||||
o.separator "Releases a version entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@env.ui.warn(I18n.t("cloud_command.version.release_warn", version: argv[1], box: argv.first))
|
||||
continue = @env.ui.ask(I18n.t("cloud_command.continue"))
|
||||
return 1 if continue.downcase != "y"
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
version = argv[1]
|
||||
|
||||
release_version(org, box_name, version, @client.token, options)
|
||||
end
|
||||
|
||||
def release_version(org, box_name, version, access_token, options)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
version = VagrantCloud::Version.new(box, version, nil, nil, access_token)
|
||||
|
||||
begin
|
||||
success = version.release
|
||||
@env.ui.success(I18n.t("cloud_command.version.release_success", version: version, org: org, box_name: box_name))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.version.release_fail", version: version, org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
module Command
|
||||
class Revoke < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud version revoke [options] organization/box-name version"
|
||||
o.separator ""
|
||||
o.separator "Revokes a version entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@env.ui.warn(I18n.t("cloud_command.version.revoke_warn", version: argv[1], box: argv.first))
|
||||
continue = @env.ui.ask(I18n.t("cloud_command.continue"))
|
||||
return 1 if continue.downcase != "y"
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
version = argv[1]
|
||||
|
||||
revoke_version(org, box_name, version, @client.token, options)
|
||||
end
|
||||
|
||||
def revoke_version(org, box_name, box_version, access_token, options)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
version = VagrantCloud::Version.new(box, box_version, nil, nil, access_token)
|
||||
|
||||
begin
|
||||
success = version.revoke
|
||||
@env.ui.success(I18n.t("cloud_command.version.revoke_success", version: box_version, org: org, box_name: box_name))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.version.revoke_fail", version: box_version, org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,81 @@
|
|||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
module Command
|
||||
class Root < Vagrant.plugin("2", :command)
|
||||
def self.synopsis
|
||||
"Version commands"
|
||||
end
|
||||
|
||||
def initialize(argv, env)
|
||||
super
|
||||
|
||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||
@subcommands = Vagrant::Registry.new
|
||||
@subcommands.register(:create) do
|
||||
require File.expand_path("../create", __FILE__)
|
||||
Command::Create
|
||||
end
|
||||
@subcommands.register(:delete) do
|
||||
require File.expand_path("../delete", __FILE__)
|
||||
Command::Delete
|
||||
end
|
||||
@subcommands.register(:revoke) do
|
||||
require File.expand_path("../revoke", __FILE__)
|
||||
Command::Revoke
|
||||
end
|
||||
@subcommands.register(:release) do
|
||||
require File.expand_path("../release", __FILE__)
|
||||
Command::Release
|
||||
end
|
||||
@subcommands.register(:update) do
|
||||
require File.expand_path("../update", __FILE__)
|
||||
Command::Update
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
if @main_args.include?("-h") || @main_args.include?("--help")
|
||||
# Print the help for all the version commands.
|
||||
return help
|
||||
end
|
||||
|
||||
# If we reached this far then we must have a subcommand. If not,
|
||||
# then we also just print the help and exit.
|
||||
command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
|
||||
return help if !command_class || !@sub_command
|
||||
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
||||
|
||||
# Initialize and execute the command class
|
||||
command_class.new(@sub_args, @env).execute
|
||||
end
|
||||
|
||||
# Prints the help out for this command
|
||||
def help
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: vagrant cloud version <subcommand> [<args>]"
|
||||
opts.separator ""
|
||||
opts.separator "For taking various actions against a Vagrant boxes version attribute on Vagrant Cloud"
|
||||
opts.separator ""
|
||||
opts.separator "Available subcommands:"
|
||||
|
||||
# Add the available subcommands as separators in order to print them
|
||||
# out as well.
|
||||
keys = []
|
||||
@subcommands.each { |key, value| keys << key.to_s }
|
||||
|
||||
keys.sort.each do |key|
|
||||
opts.separator " #{key}"
|
||||
end
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "For help on any individual subcommand run `vagrant cloud version <subcommand> -h`"
|
||||
end
|
||||
|
||||
@env.ui.info(opts.help, prefix: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
require 'optparse'
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
module VersionCommand
|
||||
module Command
|
||||
class Update < Vagrant.plugin("2", :command)
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant cloud version update [options] organization/box-name version"
|
||||
o.separator ""
|
||||
o.separator "Updates a version entry on Vagrant Cloud"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-d", "--description DESCRIPTION", "A description for this version") do |d|
|
||||
options[:description] = d
|
||||
end
|
||||
o.on("-u", "--username USERNAME_OR_EMAIL", String, "Specify your Vagrant Cloud username or email address") do |t|
|
||||
options[:username] = u
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
if argv.empty? || argv.length > 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage,
|
||||
help: opts.help.chomp
|
||||
end
|
||||
|
||||
@client = VagrantPlugins::CloudCommand::Util.client_login(@env, options[:username])
|
||||
box = argv.first.split('/')
|
||||
org = box[0]
|
||||
box_name = box[1]
|
||||
version = argv[1]
|
||||
|
||||
update_version(org, box_name, version, @client.token, options)
|
||||
end
|
||||
|
||||
def update_version(org, box_name, box_version, access_token, options)
|
||||
org = options[:username] if options[:username]
|
||||
|
||||
server_url = VagrantPlugins::CloudCommand::Util.api_server_url
|
||||
account = VagrantPlugins::CloudCommand::Util.account?(org, access_token, server_url)
|
||||
box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token)
|
||||
version = VagrantCloud::Version.new(box, box_version, nil, options[:description], access_token)
|
||||
|
||||
begin
|
||||
success = version.update
|
||||
@env.ui.success(I18n.t("cloud_command.version.update_success", version: box_version, org: org, box_name: box_name))
|
||||
VagrantPlugins::CloudCommand::Util.format_box_results(success.compact, @env)
|
||||
return 0
|
||||
rescue VagrantCloud::ClientError => e
|
||||
@env.ui.error(I18n.t("cloud_command.errors.version.update_fail", version: box_version, org: org, box_name: box_name))
|
||||
@env.ui.error(e)
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,103 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/auth/login")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::AuthCommand::Command::Login do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:env) { isolated_environment.create_vagrant_env }
|
||||
|
||||
let(:token_path) { env.data_dir.join("vagrant_login_token") }
|
||||
|
||||
let(:stdout) { StringIO.new }
|
||||
let(:stderr) { StringIO.new }
|
||||
|
||||
subject { described_class.new(argv, env) }
|
||||
|
||||
before do
|
||||
stub_env("ATLAS_TOKEN" => "")
|
||||
end
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
before do
|
||||
allow(env).to receive(:action_runner).and_return(action_runner)
|
||||
end
|
||||
|
||||
describe "#execute" do
|
||||
context "with no args" do
|
||||
let(:argv) { [] }
|
||||
end
|
||||
|
||||
context "with --check" do
|
||||
let(:argv) { ["--check"] }
|
||||
|
||||
context "when there is a token" do
|
||||
before do
|
||||
stub_request(:get, %r{^#{Vagrant.server_url}/api/v1/authenticate})
|
||||
.to_return(status: 200)
|
||||
end
|
||||
|
||||
before do
|
||||
File.open(token_path, "w+") { |f| f.write("abcd1234") }
|
||||
end
|
||||
|
||||
it "returns 0" do
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is no token" do
|
||||
it "returns 1" do
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with --logout" do
|
||||
let(:argv) { ["--logout"] }
|
||||
|
||||
it "returns 0" do
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "clears the token" do
|
||||
subject.execute
|
||||
expect(File.exist?(token_path)).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "with --token" do
|
||||
let(:argv) { ["--token", "efgh5678"] }
|
||||
|
||||
context "when the token is valid" do
|
||||
before do
|
||||
stub_request(:get, %r{^#{Vagrant.server_url}/api/v1/authenticate})
|
||||
.to_return(status: 200)
|
||||
end
|
||||
|
||||
it "sets the token" do
|
||||
subject.execute
|
||||
token = File.read(token_path).strip
|
||||
expect(token).to eq("efgh5678")
|
||||
end
|
||||
|
||||
it "returns 0" do
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the token is invalid" do
|
||||
before do
|
||||
stub_request(:get, %r{^#{Vagrant.server_url}/api/v1/authenticate})
|
||||
.to_return(status: 401)
|
||||
end
|
||||
|
||||
it "returns 1" do
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/auth/logout")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::AuthCommand::Command::Logout do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
end
|
||||
|
||||
context "with any arguments" do
|
||||
let (:argv) { ["stuff", "things"] }
|
||||
|
||||
it "shows the help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "logs you out" do
|
||||
expect(client).to receive(:clear_token)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/auth/whoami")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::AuthCommand::Command::Whoami do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:account) { double("account") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:account?).
|
||||
and_return(account)
|
||||
end
|
||||
|
||||
context "with too many arguments" do
|
||||
let(:argv) { ["token", "token", "token"] }
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with username" do
|
||||
let(:argv) { ["token"] }
|
||||
let(:org_hash) { {"user"=>{"username"=>"mario"}, "boxes"=>[{"name"=>"box"}]} }
|
||||
|
||||
it "gets information about a user" do
|
||||
expect(account).to receive(:validate_token).and_return(org_hash)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "returns 1 if encountering an error making request" do
|
||||
allow(account).to receive(:validate_token).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/box/create")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::BoxCommand::Command::Create do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "-s", "short", "-d", "long"] }
|
||||
|
||||
it "creates a box" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, "short", "long", client.token)
|
||||
.and_return(box)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(box).to receive(:create).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, "short", "long", client.token)
|
||||
.and_return(box)
|
||||
|
||||
allow(box).to receive(:create).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/box/delete")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::BoxCommand::Command::Delete do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name"] }
|
||||
|
||||
it "creates a box" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
|
||||
expect(box).to receive(:delete).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
|
||||
allow(box).to receive(:delete).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,63 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/box/show")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::BoxCommand::Command::Show do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name"] }
|
||||
|
||||
it "creates a box" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
|
||||
expect(box).to receive(:read).and_return({})
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
|
||||
allow(box).to receive(:read).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,64 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/box/update")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::BoxCommand::Command::Update do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "-d", "update", "-s", "short"] }
|
||||
|
||||
it "creates a box" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
|
||||
expect(box).to receive(:update).
|
||||
with(organization: "vagrant", name: "box-name", description: "update", short_description: "short").
|
||||
and_return({})
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
|
||||
allow(box).to receive(:update).
|
||||
with(organization: "vagrant", name: "box-name", description: "update", short_description: "short").
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,261 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/client/client")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::Client do
|
||||
include_context "unit"
|
||||
|
||||
let(:env) { isolated_environment.create_vagrant_env }
|
||||
|
||||
subject(:client) { described_class.new(env) }
|
||||
|
||||
before(:all) do
|
||||
I18n.load_path << Vagrant.source_root.join("plugins/commands/cloud/locales/en.yml")
|
||||
I18n.reload!
|
||||
end
|
||||
|
||||
before do
|
||||
stub_env("ATLAS_TOKEN" => nil)
|
||||
subject.clear_token
|
||||
end
|
||||
|
||||
describe "#logged_in?" do
|
||||
let(:url) { "#{Vagrant.server_url}/api/v1/authenticate?access_token=#{token}" }
|
||||
let(:headers) { { "Content-Type" => "application/json" } }
|
||||
|
||||
before { allow(subject).to receive(:token).and_return(token) }
|
||||
|
||||
context "when there is no token" do
|
||||
let(:token) { nil }
|
||||
|
||||
it "returns false" do
|
||||
expect(subject.logged_in?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a token" do
|
||||
let(:token) { "ABCD1234" }
|
||||
|
||||
it "returns true if the endpoint returns a 200" do
|
||||
stub_request(:get, url)
|
||||
.with(headers: headers)
|
||||
.to_return(body: JSON.pretty_generate("token" => token))
|
||||
expect(subject.logged_in?).to be(true)
|
||||
end
|
||||
|
||||
it "raises an error if the endpoint returns a non-200" do
|
||||
stub_request(:get, url)
|
||||
.with(headers: headers)
|
||||
.to_return(body: JSON.pretty_generate("bad" => true), status: 401)
|
||||
expect(subject.logged_in?).to be(false)
|
||||
end
|
||||
|
||||
it "raises an exception if the server cannot be found" do
|
||||
stub_request(:get, url)
|
||||
.to_raise(SocketError)
|
||||
expect { subject.logged_in? }
|
||||
.to raise_error(VagrantPlugins::CloudCommand::Errors::ServerUnreachable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#login" do
|
||||
let(:request) {
|
||||
{
|
||||
user: {
|
||||
login: login,
|
||||
password: password,
|
||||
},
|
||||
token: {
|
||||
description: description,
|
||||
},
|
||||
two_factor: {
|
||||
code: nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let(:login) { "foo" }
|
||||
let(:password) { "bar" }
|
||||
let(:description) { "Token description" }
|
||||
|
||||
let(:headers) {
|
||||
{
|
||||
"Accept" => "application/json",
|
||||
"Content-Type" => "application/json",
|
||||
}
|
||||
}
|
||||
let(:response) {
|
||||
{
|
||||
token: "baz"
|
||||
}
|
||||
}
|
||||
|
||||
it "returns the access token after successful login" do
|
||||
stub_request(:post, "#{Vagrant.server_url}/api/v1/authenticate").
|
||||
with(body: JSON.dump(request), headers: headers).
|
||||
to_return(status: 200, body: JSON.dump(response))
|
||||
|
||||
client.username_or_email = login
|
||||
client.password = password
|
||||
|
||||
expect(client.login(description: "Token description")).to eq("baz")
|
||||
end
|
||||
|
||||
context "when 2fa is required" do
|
||||
let(:response) {
|
||||
{
|
||||
two_factor: {
|
||||
default_delivery_method: default_delivery_method,
|
||||
delivery_methods: delivery_methods
|
||||
}
|
||||
}
|
||||
}
|
||||
let(:default_delivery_method) { "app" }
|
||||
let(:delivery_methods) { ["app"] }
|
||||
|
||||
before do
|
||||
stub_request(:post, "#{Vagrant.server_url}/api/v1/authenticate").
|
||||
to_return(status: 406, body: JSON.dump(response))
|
||||
end
|
||||
|
||||
it "raises a two-factor required error" do
|
||||
expect {
|
||||
client.login
|
||||
}.to raise_error(VagrantPlugins::CloudCommand::Errors::TwoFactorRequired)
|
||||
end
|
||||
|
||||
context "when the default delivery method is not app" do
|
||||
let(:default_delivery_method) { "sms" }
|
||||
let(:delivery_methods) { ["app", "sms"] }
|
||||
|
||||
it "requests a code and then raises a two-factor required error" do
|
||||
expect(client)
|
||||
.to receive(:request_code)
|
||||
.with(default_delivery_method)
|
||||
|
||||
expect {
|
||||
client.login
|
||||
}.to raise_error(VagrantPlugins::CloudCommand::Errors::TwoFactorRequired)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "on bad login" do
|
||||
before do
|
||||
stub_request(:post, "#{Vagrant.server_url}/api/v1/authenticate").
|
||||
to_return(status: 401, body: "")
|
||||
end
|
||||
|
||||
it "raises an error" do
|
||||
expect {
|
||||
client.login
|
||||
}.to raise_error(VagrantPlugins::CloudCommand::Errors::Unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context "if it can't reach the server" do
|
||||
before do
|
||||
stub_request(:post, "#{Vagrant.server_url}/api/v1/authenticate").
|
||||
to_raise(SocketError)
|
||||
end
|
||||
|
||||
it "raises an exception" do
|
||||
expect {
|
||||
subject.login
|
||||
}.to raise_error(VagrantPlugins::CloudCommand::Errors::ServerUnreachable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#request_code" do
|
||||
let(:request) {
|
||||
{
|
||||
user: {
|
||||
login: login,
|
||||
password: password,
|
||||
},
|
||||
two_factor: {
|
||||
delivery_method: delivery_method
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let(:login) { "foo" }
|
||||
let(:password) { "bar" }
|
||||
let(:delivery_method) { "sms" }
|
||||
|
||||
let(:headers) {
|
||||
{
|
||||
"Accept" => "application/json",
|
||||
"Content-Type" => "application/json"
|
||||
}
|
||||
}
|
||||
|
||||
let(:response) {
|
||||
{
|
||||
two_factor: {
|
||||
obfuscated_destination: "SMS number ending in 1234"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it "displays that the code was sent" do
|
||||
expect(env.ui)
|
||||
.to receive(:success)
|
||||
.with("2FA code sent to SMS number ending in 1234.")
|
||||
|
||||
stub_request(:post, "#{Vagrant.server_url}/api/v1/two-factor/request-code").
|
||||
with(body: JSON.dump(request), headers: headers).
|
||||
to_return(status: 201, body: JSON.dump(response))
|
||||
|
||||
client.username_or_email = login
|
||||
client.password = password
|
||||
|
||||
client.request_code delivery_method
|
||||
end
|
||||
end
|
||||
|
||||
describe "#token" do
|
||||
it "reads ATLAS_TOKEN" do
|
||||
stub_env("ATLAS_TOKEN" => "ABCD1234")
|
||||
expect(subject.token).to eq("ABCD1234")
|
||||
end
|
||||
|
||||
it "reads the stored file" do
|
||||
subject.store_token("EFGH5678")
|
||||
expect(subject.token).to eq("EFGH5678")
|
||||
end
|
||||
|
||||
it "prefers the environment variable" do
|
||||
stub_env("VAGRANT_CLOUD_TOKEN" => "ABCD1234")
|
||||
subject.store_token("EFGH5678")
|
||||
expect(subject.token).to eq("ABCD1234")
|
||||
end
|
||||
|
||||
it "prints a warning if the envvar and stored file are both present" do
|
||||
stub_env("VAGRANT_CLOUD_TOKEN" => "ABCD1234")
|
||||
subject.store_token("EFGH5678")
|
||||
expect(env.ui).to receive(:warn).with(/detected both/)
|
||||
subject.token
|
||||
end
|
||||
|
||||
it "returns nil if there's no token set" do
|
||||
expect(subject.token).to be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#store_token, #clear_token" do
|
||||
it "stores the token and can re-access it" do
|
||||
subject.store_token("foo")
|
||||
expect(subject.token).to eq("foo")
|
||||
expect(described_class.new(env).token).to eq("foo")
|
||||
end
|
||||
|
||||
it "deletes the token" do
|
||||
subject.store_token("foo")
|
||||
subject.clear_token
|
||||
expect(subject.token).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/list")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::Command::List do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,85 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/provider/create")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Create do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
let(:provider) { double("provider") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(VagrantCloud::Version).to receive(:new)
|
||||
.with(box, "1.0.0", nil, nil, client.token)
|
||||
.and_return(version)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "virtualbox", "1.0.0"] }
|
||||
|
||||
it "creates a provider" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(iso_env.ui).to receive(:warn)
|
||||
expect(provider).to receive(:create_provider).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
allow(provider).to receive(:create_provider).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments and a remote url" do
|
||||
let (:argv) { ["vagrant/box-name", "virtualbox", "1.0.0", "https://box.com/box"] }
|
||||
|
||||
it "creates a provider" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, "https://box.com/box", "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(iso_env.ui).not_to receive(:warn)
|
||||
expect(provider).to receive(:create_provider).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/provider/delete")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Delete do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
let(:provider) { double("provider") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(VagrantCloud::Version).to receive(:new)
|
||||
.with(box, "1.0.0", nil, nil, client.token)
|
||||
.and_return(version)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "virtualbox", "1.0.0"] }
|
||||
|
||||
it "deletes a provider" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, nil, nil, client.token).
|
||||
and_return(provider)
|
||||
|
||||
expect(provider).to receive(:delete).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, nil, nil, client.token).
|
||||
and_return(provider)
|
||||
|
||||
allow(provider).to receive(:delete).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,85 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/provider/update")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box", create: true, read: {}) }
|
||||
let(:version) { double("version", create_version: true, release: true) }
|
||||
let(:provider) { double("provider", create_provider: true, upload_file: true) }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(VagrantCloud::Version).to receive(:new)
|
||||
.with(box, "1.0.0", nil, nil, client.token)
|
||||
.and_return(version)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "virtualbox", "1.0.0"] }
|
||||
|
||||
it "updates a provider" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(iso_env.ui).to receive(:warn)
|
||||
expect(provider).to receive(:update).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
allow(provider).to receive(:update).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments and a remote url" do
|
||||
let (:argv) { ["vagrant/box-name", "virtualbox", "1.0.0", "https://box.com/box"] }
|
||||
|
||||
it "creates a provider" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, "https://box.com/box", "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(iso_env.ui).not_to receive(:warn)
|
||||
expect(provider).to receive(:update).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/provider/upload")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Upload do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
let(:provider) { double("provider") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(VagrantCloud::Version).to receive(:new)
|
||||
.with(box, "1.0.0", nil, nil, client.token)
|
||||
.and_return(version)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "virtualbox", "1.0.0", "path/to/box.box"] }
|
||||
|
||||
it "uploads a provider" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
expect(provider).to receive(:upload_file).
|
||||
with("path/to/box.box").
|
||||
and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Provider).to receive(:new).
|
||||
with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token).
|
||||
and_return(provider)
|
||||
|
||||
allow(provider).to receive(:upload_file).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,80 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/publish")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::Command::Publish do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:box) { double("box", create: true, read: {}) }
|
||||
let(:version) { double("version", create_version: true, release: true) }
|
||||
let(:provider) { double("provider", create_provider: true, upload_file: true) }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
allow(VagrantCloud::Box).to receive(:new).and_return(box)
|
||||
allow(VagrantCloud::Version).to receive(:new).and_return(version)
|
||||
allow(VagrantCloud::Provider).to receive(:new).and_return(provider)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let(:argv) { ["vagrant/box", "1.0.0", "virtualbox", "path/to/the/virtualbox.box"] }
|
||||
|
||||
it "publishes a box given options" do
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "catches a ClientError if something goes wrong" do
|
||||
allow(box).to receive(:create).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments and releasing a box" do
|
||||
let(:argv) { ["vagrant/box", "1.0.0", "virtualbox", "path/to/the/virtualbox.box", "--release"] }
|
||||
|
||||
it "releases the box" do
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(version).to receive(:release)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments and a remote url" do
|
||||
let(:argv) { ["vagrant/box", "1.0.0", "virtualbox", "--url", "https://www.boxes.com/path/to/the/virtualbox.box"] }
|
||||
|
||||
it "does not upload a file" do
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(subject.execute).to eq(0)
|
||||
expect(provider).not_to receive(:upload_file)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/search")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::Command::Search do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_search_results).
|
||||
and_return(true)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
let (:search) { double("search", search: {"boxes"=>["all of them"]}) }
|
||||
|
||||
it "makes a request to search all boxes and formats them" do
|
||||
allow(VagrantCloud::Search).to receive(:new).
|
||||
and_return(search)
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_search_results)
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "with no arguments and an error occurs making requests" do
|
||||
let (:search) { double("search") }
|
||||
|
||||
it "catches a ClientError if something goes wrong" do
|
||||
allow(VagrantCloud::Search).to receive(:new).
|
||||
and_return(search)
|
||||
allow(search).to receive(:search).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "with no arguments and no results" do
|
||||
let (:search) { double("search", search: {"boxes"=>[]}) }
|
||||
|
||||
it "makes a request to search all boxes and formats them" do
|
||||
allow(VagrantCloud::Search).to receive(:new).
|
||||
and_return(search)
|
||||
expect(VagrantPlugins::CloudCommand::Util).not_to receive(:format_search_results)
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:search) { double("search", search: {"boxes"=>["all of them"]}) }
|
||||
let (:argv) { ["ubuntu", "--page", "1", "--order", "desc", "--limit", "100", "--provider", "provider", "--sort", "downloads"] }
|
||||
|
||||
it "sends the options to make a request with" do
|
||||
allow(VagrantCloud::Search).to receive(:new).
|
||||
and_return(search)
|
||||
expect(search).to receive(:search).
|
||||
with("ubuntu", "provider", "downloads", "desc", 100, 1)
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,65 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/version/create")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::VersionCommand::Command::Create do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "1.0.0", "-d", "description"] }
|
||||
|
||||
it "creates a version" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, "description", client.token).
|
||||
and_return(version)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(version).to receive(:create_version).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, "description", client.token).
|
||||
and_return(version)
|
||||
|
||||
allow(version).to receive(:create_version).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/version/delete")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::VersionCommand::Command::Delete do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "1.0.0"] }
|
||||
|
||||
it "deletes a version" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, nil, client.token).
|
||||
and_return(version)
|
||||
|
||||
expect(version).to receive(:delete).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, nil, client.token).
|
||||
and_return(version)
|
||||
|
||||
allow(version).to receive(:delete).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/version/release")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::VersionCommand::Command::Release do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "1.0.0"] }
|
||||
|
||||
it "releases a version" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, nil, client.token).
|
||||
and_return(version)
|
||||
|
||||
expect(version).to receive(:release).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, nil, client.token).
|
||||
and_return(version)
|
||||
|
||||
allow(version).to receive(:release).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/version/revoke")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::VersionCommand::Command::Revoke do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
allow(iso_env.ui).to receive(:ask).
|
||||
and_return("y")
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "1.0.0"] }
|
||||
|
||||
it "revokes a version" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, nil, client.token).
|
||||
and_return(version)
|
||||
|
||||
expect(version).to receive(:revoke).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, nil, client.token).
|
||||
and_return(version)
|
||||
|
||||
expect(version).to receive(:revoke).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,65 @@
|
|||
require File.expand_path("../../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/version/update")
|
||||
|
||||
describe VagrantPlugins::CloudCommand::VersionCommand::Command::Update do
|
||||
include_context "unit"
|
||||
|
||||
let(:argv) { [] }
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
let(:action_runner) { double("action_runner") }
|
||||
|
||||
let(:client) { double("client", token: "1234token1234") }
|
||||
let(:box) { double("box") }
|
||||
let(:version) { double("version") }
|
||||
|
||||
before do
|
||||
allow(iso_env).to receive(:action_runner).and_return(action_runner)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:client_login).
|
||||
and_return(client)
|
||||
allow(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results).
|
||||
and_return(true)
|
||||
allow(VagrantCloud::Box).to receive(:new)
|
||||
.with(anything, "box-name", nil, nil, nil, client.token)
|
||||
.and_return(box)
|
||||
end
|
||||
|
||||
context "with no arguments" do
|
||||
it "shows help" do
|
||||
expect { subject.execute }.
|
||||
to raise_error(Vagrant::Errors::CLIInvalidUsage)
|
||||
end
|
||||
end
|
||||
|
||||
context "with arguments" do
|
||||
let (:argv) { ["vagrant/box-name", "1.0.0", "-d", "description"] }
|
||||
|
||||
it "updates a version" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, "description", client.token).
|
||||
and_return(version)
|
||||
|
||||
expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results)
|
||||
expect(version).to receive(:update).and_return({})
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
|
||||
it "displays an error if encoutering a problem with the request" do
|
||||
allow(VagrantCloud::Version).to receive(:new).
|
||||
with(box, "1.0.0", nil, "description", client.token).
|
||||
and_return(version)
|
||||
|
||||
allow(version).to receive(:update).
|
||||
and_raise(VagrantCloud::ClientError.new("Fail Message", "Message"))
|
||||
expect(subject.execute).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -32,6 +32,7 @@ Gem::Specification.new do |s|
|
|||
s.add_dependency "winrm", "~> 2.1"
|
||||
s.add_dependency "winrm-fs", "~> 1.0"
|
||||
s.add_dependency "winrm-elevated", "~> 1.1"
|
||||
s.add_dependency "vagrant_cloud", "~> 2.0.0"
|
||||
|
||||
# NOTE: The ruby_dep gem is an implicit dependency from the listen gem. Later versions
|
||||
# of the ruby_dep gem impose an aggressive constraint on the required ruby version (>= 2.2.5).
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "vagrant cloud - Command-Line Interface"
|
||||
sidebar_current: "cli-cloud"
|
||||
description: |-
|
||||
The "vagrant cloud" command can be used for taking actions against
|
||||
Vagrant Cloud like searching or uploading a Vagrant Box
|
||||
---
|
||||
|
||||
# Cloud
|
||||
|
||||
**Command: `vagrant cloud`**
|
||||
|
||||
This is the command used to manage anything related to [Vagrant Cloud](https://vagrantcloud.com)
|
||||
|
||||
The main functionality of this command is exposed via even more subcommands:
|
||||
|
||||
* [`auth`](#cloud-auth)
|
||||
* [`box`](#cloud-box)
|
||||
* [`provider`](#cloud-provider)
|
||||
* [`publish`](#cloud-publish)
|
||||
* [`search`](#cloud-search)
|
||||
* [`version`](#cloud-version)
|
||||
|
||||
# Cloud Auth
|
||||
|
||||
**Command: `vagrant cloud auth`**
|
||||
|
||||
Information about this subcommand goes here
|
||||
|
||||
* [`login`](#cloud-auth-login)
|
||||
* [`logout`](#cloud-auth-logout)
|
||||
* [`who`](#cloud-auth-who)
|
||||
|
||||
## Cloud Auth Login
|
||||
|
||||
**Command: `vagrant cloud auth login`**
|
||||
|
||||
The login command is used to authenticate with the
|
||||
[HashiCorp's Vagrant Cloud](/docs/vagrant-cloud) server. Logging is only
|
||||
necessary if you are accessing protected boxes or using
|
||||
[Vagrant Share](/docs/share/).
|
||||
|
||||
**Logging in is not a requirement to use Vagrant.** The vast majority
|
||||
of Vagrant does _not_ require a login. Only certain features such as protected
|
||||
boxes or [Vagrant Share](/docs/share/) require a login.
|
||||
|
||||
The reference of available command-line flags to this command
|
||||
is available below.
|
||||
|
||||
### Options
|
||||
|
||||
* `--check` - This will check if you are logged in. In addition to outputting
|
||||
whether you are logged in or not, the command will have exit status 0 if you are
|
||||
logged in, and exit status 1 if you are not.
|
||||
|
||||
* `--logout` - This will log you out if you are logged in. If you are already
|
||||
logged out, this command will do nothing. It is not an error to call this
|
||||
command if you are already logged out.
|
||||
|
||||
* `--token` - This will set the Vagrant Cloud login token manually to the provided
|
||||
string. It is assumed this token is a valid Vagrant Cloud access token.
|
||||
|
||||
### Examples
|
||||
|
||||
Securely authenticate to Vagrant Cloud using a username and password:
|
||||
|
||||
```text
|
||||
$ vagrant cloud auth login
|
||||
# ...
|
||||
Vagrant Cloud username:
|
||||
Vagrant Cloud password:
|
||||
```
|
||||
|
||||
Check if the current user is authenticated:
|
||||
|
||||
```text
|
||||
$ vagrant cloud auth login --check
|
||||
You are already logged in.
|
||||
```
|
||||
|
||||
Securely authenticate with Vagrant Cloud using a token:
|
||||
|
||||
```text
|
||||
$ vagrant cloud auth login --token ABCD1234
|
||||
The token was successfully saved.
|
||||
```
|
||||
|
||||
## Cloud Auth Logout
|
||||
|
||||
**Command: `vagrant cloud auth logout`**
|
||||
|
||||
This will log you out if you are logged in. If you are already
|
||||
logged out, this command will do nothing. It is not an error to call this
|
||||
command if you are already logged out.
|
||||
|
||||
## Cloud Auth Whomi
|
||||
|
||||
**Command: `vagrant cloud auth whoami [TOKEN]`**
|
||||
|
||||
This command will validate your Vagrant Cloud token and will print the user who
|
||||
it belongs to. If a token is passed in, it will attempt to validate it instead
|
||||
of the token stored stored on disk.
|
||||
|
||||
# Cloud Box
|
||||
|
||||
**Command: `vagrant cloud box`**
|
||||
|
||||
The `cloud box` command is used to manage CRUD operations for all `box` entities on
|
||||
Vagrant Cloud.
|
||||
|
||||
* [`create`](#cloud-box-create)
|
||||
* [`delete`](#cloud-box-delete)
|
||||
* [`show`](#cloud-box-show)
|
||||
* [`update`](#cloud-box-update)
|
||||
|
||||
## Cloud Box Create
|
||||
|
||||
**Command: `vagrant cloud box create ORGANIZATION/BOX-NAME`**
|
||||
|
||||
The box create command is used to create a new box entry on Vagrant Cloud.
|
||||
|
||||
### Options
|
||||
|
||||
* `--description DESCRIPTION` - A longer description of the box. Can be
|
||||
formatted with Markdown.
|
||||
* `--short-description DESCRIPTION` - A short summary of the box.
|
||||
* `--private` - Will make the new box private (Public by default)
|
||||
|
||||
## Cloud Box Delete
|
||||
|
||||
**Command: `vagrant cloud box delete ORGANIZATION/BOX-NAME`**
|
||||
|
||||
The box delete command will _permanently_ delete the given box entry on Vagrant Cloud. Before
|
||||
making the request, it will ask if you are sure you want to delete the box.
|
||||
|
||||
## Cloud Box Show
|
||||
|
||||
**Command: `vagrant cloud box show ORGANIZATION/BOX-NAME`**
|
||||
|
||||
The box show command will display information about the latest version for the given Vagrant box.
|
||||
|
||||
## Cloud Box Update
|
||||
|
||||
**Command: `vagrant cloud box update ORGANIZATION/BOX-NAME`**
|
||||
|
||||
The box update command will update an already created box on Vagrant Cloud with the given options.
|
||||
|
||||
### Options
|
||||
|
||||
* `--description DESCRIPTION` - A longer description of the box. Can be
|
||||
formatted with Markdown.
|
||||
* `--short-description DESCRIPTION` - A short summary of the box.
|
||||
* `--private` - Will make the new box private (Public by default)
|
||||
|
||||
# Cloud Provider
|
||||
|
||||
**Command: `vagrant cloud provider`**
|
||||
|
||||
The `cloud provider` command is used to manage CRUD operations for all `provider` entities on
|
||||
Vagrant Cloud.
|
||||
|
||||
* [`create`](#cloud-provider-create)
|
||||
* [`delete`](#cloud-provider-delete)
|
||||
* [`update`](#cloud-provider-update)
|
||||
* [`upload`](#cloud-provider-upload)
|
||||
|
||||
## Cloud Provider Create
|
||||
|
||||
**Command: `vagrant cloud provider create ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION [URL]`**
|
||||
|
||||
|
||||
The provider create command is used to create a new provider entry on Vagrant Cloud.
|
||||
The `url` argument is expected to be a valid remote URL that Vagrant Cloud can use
|
||||
to download the provider. If no `url` is specified, the provider entry can be updated
|
||||
later with a url or the [upload](#cloud-provider-upload) command can be used to
|
||||
upload a Vagrant [box file](/docs/boxes.html).
|
||||
|
||||
## Cloud Provider Delete
|
||||
|
||||
**Command: `vagrant cloud provider delete ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION`**
|
||||
|
||||
The provider delete command is used to delete a provider entry on Vagrant Cloud.
|
||||
Before making the request, it will ask if you are sure you want to delete the provider.
|
||||
|
||||
## Cloud Provider Update
|
||||
|
||||
**Command: `vagrant cloud provider update ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION [URL]`**
|
||||
|
||||
The provider update command will update an already created provider for a box on
|
||||
Vagrant Cloud with the given options.
|
||||
|
||||
## Cloud Provider Upload
|
||||
|
||||
**Command: `vagrant cloud provider upload ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION BOX-FILE`**
|
||||
|
||||
The provider upload command will upload a Vagrant [box file](/docs/boxes.html) to Vagrant Cloud for
|
||||
the specified version and provider.
|
||||
|
||||
# Cloud Publish
|
||||
|
||||
**Command: `vagrant cloud publish ORGANIZATION/BOX-NAME VERSION PROVIDER-NAME [PROVIDER-FILE]`**
|
||||
|
||||
The publish command is a start-to-finish solution for creating and updating a
|
||||
Vagrant box on Vagrant Cloud. Instead of having to create each attribute of a Vagrant
|
||||
box with separate commands, the publish command instead askes you to provide all
|
||||
the information you need up front to create or update a new box.
|
||||
|
||||
## Options
|
||||
|
||||
* `--box-version VERSION` - Version to create for the box
|
||||
* `--description DESCRIPTION` - A longer description of the box. Can be
|
||||
formatted with Markdown.
|
||||
* `--force` - Disables confirmation when creating or updating a box.
|
||||
* `--short-description DESCRIPTION` - A short summary of the box.
|
||||
* `--private` - Will make the new box private (Public by default)
|
||||
* `--release` - Automatically releases the box after creation (Unreleased by default)
|
||||
* `--url` - Valid remote URL to download the box file
|
||||
* `--version-description DESCRIPTION` - Description of the version that will be created.
|
||||
|
||||
## Examples
|
||||
|
||||
Creating a new box on Vagrant Cloud
|
||||
|
||||
```text
|
||||
$ vagrant cloud publish briancain/supertest 1.0.0 virtualbox boxes/my/virtualbox.box -d "A really cool box to download and use" --version-description "A cool version" --release --short-description "Donwload me!"
|
||||
You are about to create a box on Vagrant Cloud with the following options:
|
||||
|
||||
briancain/supertest (1.0.0) for virtualbox
|
||||
Automatic Release: true
|
||||
Box Description: A really cool box to download and use
|
||||
Box Short Description: Download me!
|
||||
Version Description: A cool version
|
||||
|
||||
Do you wish to continue? [y/N] y
|
||||
Creating a box entry...
|
||||
Creating a version entry...
|
||||
Creating a provider entry...
|
||||
Uploading provider with file boxes/my/virtualbox.box
|
||||
Releasing box...
|
||||
Complete! Published briancain/supertest
|
||||
tag: briancain/supertest
|
||||
username: briancain
|
||||
name: supertest
|
||||
private: false
|
||||
downloads: 0
|
||||
created_at: 2018-07-25T17:53:04.340Z
|
||||
updated_at: 2018-07-25T18:01:10.665Z
|
||||
short_description: Download me!
|
||||
description_markdown: A reall cool box to download and use
|
||||
current_version: 1.0.0
|
||||
providers: virtualbox
|
||||
```
|
||||
|
||||
# Cloud Search
|
||||
|
||||
**Command: `vagrant cloud search QUERY`**
|
||||
|
||||
The cloud search command will take a query and search Vagrant Cloud for any matching
|
||||
Vagrant boxes. Various filters can be applied to the results.
|
||||
|
||||
## Options
|
||||
|
||||
* `--json` - Format search results in JSON.
|
||||
* `--page PAGE` - The page to display. Defaults to the first page of results.
|
||||
* `--short` - Shows a simple list of box names for the results.
|
||||
* `--order ORDER` - Order to display results. Can either be `desc` or `asc`.
|
||||
Defaults to `desc`.
|
||||
* `--limit LIMIT` - Max number of search results to display. Defaults to 25.
|
||||
* `--provider PROVIDER` - Filter search results to a single provider.
|
||||
* `--sort-by SORT` - The field to sort results on. Can be `created`, `downloads`
|
||||
, or `updated`. Defaults to `downloads`.
|
||||
|
||||
## Examples
|
||||
|
||||
If you are looking for a HashiCorp box:
|
||||
|
||||
```text
|
||||
vagrant cloud search hashicorp --limit 5
|
||||
| NAME | VERSION | DOWNLOADS | PROVIDERS |
|
||||
+-------------------------+---------+-----------+---------------------------------+
|
||||
| hashicorp/precise64 | 1.1.0 | 6,675,725 | virtualbox,vmware_fusion,hyperv |
|
||||
| hashicorp/precise32 | 1.0.0 | 2,261,377 | virtualbox |
|
||||
| hashicorp/boot2docker | 1.7.8 | 59,284 | vmware_desktop,virtualbox |
|
||||
| hashicorp/connect-vm | 0.1.0 | 6,912 | vmware_desktop,virtualbox |
|
||||
| hashicorp/vagrant-share | 0.1.0 | 3,488 | vmware_desktop,virtualbox |
|
||||
+-------------------------+---------+-----------+---------------------------------+
|
||||
```
|
||||
|
||||
# Cloud Version
|
||||
|
||||
**Command: `vagrant cloud version`**
|
||||
|
||||
* [`create`](#cloud-version-create)
|
||||
* [`delete`](#cloud-version-delete)
|
||||
* [`release`](#cloud-version-release)
|
||||
* [`revoke`](#cloud-version-revoke)
|
||||
* [`update`](#cloud-version-update)
|
||||
|
||||
## Cloud Version Create
|
||||
|
||||
**Command: `vagrant cloud version create ORGANIZATION/BOX-NAME VERSION`**
|
||||
|
||||
The cloud create command creates a version entry for a box on Vagrant Cloud.
|
||||
|
||||
### Options
|
||||
|
||||
* `--description DESCRIPTION` - Description of the version that will be created.
|
||||
|
||||
## Cloud Version Delete
|
||||
|
||||
**Command: `vagrant cloud version delete ORGANIZATION/BOX-NAME VERSION`**
|
||||
|
||||
The cloud delete command deletes a version entry for a box on Vagrant Cloud.
|
||||
Before making the request, it will ask if you are sure you want to delete the version.
|
||||
|
||||
## Cloud Version Release
|
||||
|
||||
**Command: `vagrant cloud version release ORGANIZATION/BOX-NAME VERSION`**
|
||||
|
||||
The cloud release command releases a version entry for a box on Vagrant Cloud
|
||||
if it already exists. Before making the request, it will ask if you are sure you
|
||||
want to release the version.
|
||||
|
||||
## Cloud Version Revoke
|
||||
|
||||
**Command: `vagrant cloud version revoke ORGANIZATION/BOX-NAME VERSION`**
|
||||
|
||||
The cloud revoke command revokes a version entry for a box on Vagrant Cloud
|
||||
if it already exists. Before making the request, it will ask if you are sure you
|
||||
want to revoke the version.
|
||||
|
||||
## Cloud Version Update
|
||||
|
||||
**Command: `vagrant cloud version update ORGANIZATION/BOX-NAME VERSION`**
|
||||
|
||||
### Options
|
||||
|
||||
* `--description DESCRIPTION` - Description of the version that will be created.
|
|
@ -20,6 +20,7 @@
|
|||
<a href="/docs/cli/">Commands (CLI)</a>
|
||||
<ul class="nav">
|
||||
<li<%= sidebar_current("cli-box") %>><a href="/docs/cli/box.html">box</a></li>
|
||||
<li<%= sidebar_current("cli-cloud") %>><a href="/docs/cli/cloud.html">cloud</a></li>
|
||||
<li<%= sidebar_current("cli-connect") %>><a href="/docs/cli/connect.html">connect</a></li>
|
||||
<li<%= sidebar_current("cli-destroy") %>><a href="/docs/cli/destroy.html">destroy</a></li>
|
||||
<li<%= sidebar_current("cli-globalstatus") %>><a href="/docs/cli/global-status.html">global-status</a></li>
|
||||
|
|
Loading…
Reference in New Issue