Merge pull request #10485 from briancain/introduce-experimental-feature-flag
Add experimental flag to guard development features
This commit is contained in:
commit
2011e213c3
18
bin/vagrant
18
bin/vagrant
|
@ -89,6 +89,7 @@ begin
|
|||
require 'vagrant/bundler'
|
||||
require 'vagrant/cli'
|
||||
require 'vagrant/util/platform'
|
||||
require 'vagrant/util/experimental'
|
||||
|
||||
# Schedule the cleanup of things
|
||||
at_exit(&Vagrant::Bundler.instance.method(:deinit))
|
||||
|
@ -159,6 +160,23 @@ begin
|
|||
env.ui.warn(I18n.t("vagrant.general.not_in_installer") + "\n", prefix: false)
|
||||
end
|
||||
|
||||
# Acceptable experimental flag values include:
|
||||
#
|
||||
# Unset - Disables experimental features
|
||||
# 0 - Disables experimental features
|
||||
# 1 - Enables all features
|
||||
# String - Enables one or more features, separated by commas
|
||||
if Vagrant::Util::Experimental.enabled?
|
||||
experimental = Vagrant::Util::Experimental.features_requested
|
||||
ui = Vagrant::UI::Prefixed.new(env.ui, "vagrant")
|
||||
logger.debug("Experimental flag is enabled")
|
||||
if Vagrant::Util::Experimental.global_enabled?
|
||||
ui.warn(I18n.t("vagrant.general.experimental.all"), bold: true, prefix: true, channel: :error)
|
||||
else
|
||||
ui.warn(I18n.t("vagrant.general.experimental.features", features: experimental.join(", ")), bold: true, prefix: true, channel: :error)
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
# Execute the CLI interface, and exit with the proper error code
|
||||
exit_status = env.cli(argv)
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
module Vagrant
|
||||
module Util
|
||||
class Experimental
|
||||
class << self
|
||||
# A method for determining if the experimental flag has been enabled with
|
||||
# any features
|
||||
#
|
||||
# @return [Boolean]
|
||||
def enabled?
|
||||
if !defined?(@_experimental)
|
||||
experimental = features_requested
|
||||
if experimental.size >= 1 && experimental.first != "0"
|
||||
@_experimental = true
|
||||
else
|
||||
@_experimental = false
|
||||
end
|
||||
end
|
||||
@_experimental
|
||||
end
|
||||
|
||||
# A method for determining if all experimental features have been enabled
|
||||
# by either a global enabled value "1" or all features explicitly enabled.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def global_enabled?
|
||||
if !defined?(@_global_enabled)
|
||||
experimental = features_requested
|
||||
if experimental.size == 1 && experimental.first == "1"
|
||||
@_global_enabled = true
|
||||
else
|
||||
@_global_enabled = false
|
||||
end
|
||||
end
|
||||
@_global_enabled
|
||||
end
|
||||
|
||||
# A method for Vagrant internals to determine if a given feature
|
||||
# has been abled by the user, is a valid feature flag and can be used.
|
||||
#
|
||||
# @param [String] feature
|
||||
# @return [Boolean] - A hash containing the original array and if it is valid
|
||||
def feature_enabled?(feature)
|
||||
experimental = features_requested
|
||||
feature = feature.to_s
|
||||
|
||||
return global_enabled? || experimental.include?(feature)
|
||||
end
|
||||
|
||||
# Returns the features requested for the experimental flag
|
||||
#
|
||||
# @return [Array] - Returns an array of requested experimental features
|
||||
def features_requested
|
||||
if !defined?(@_requested_features)
|
||||
@_requested_features = ENV["VAGRANT_EXPERIMENTAL"].to_s.downcase.split(',')
|
||||
end
|
||||
@_requested_features
|
||||
end
|
||||
|
||||
# A function to guard experimental blocks of code from being executed
|
||||
#
|
||||
# @param [Array] features - Array of features to guard a method with
|
||||
# @param [Block] block - Block of ruby code to be guarded against
|
||||
def guard_with(*features, &block)
|
||||
yield if block_given? && features.any? {|f| feature_enabled?(f)}
|
||||
end
|
||||
|
||||
# @private
|
||||
# Reset the cached values for platform. This is not considered a public
|
||||
# API and should only be used for testing.
|
||||
def reset!
|
||||
instance_variables.each(&method(:remove_instance_variable))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -393,6 +393,18 @@ en:
|
|||
shown below.
|
||||
|
||||
%{output}
|
||||
experimental:
|
||||
all: |-
|
||||
You have enabled the experimental flag with all features enabled.
|
||||
Please use with caution, as some of the features may not be fully
|
||||
functional yet.
|
||||
features: |-
|
||||
You have requested to enabled the experimental flag with the following features:
|
||||
|
||||
Features: %{features}
|
||||
|
||||
Please use with caution, as some of the features may not be fully
|
||||
functional yet.
|
||||
not_in_installer: |-
|
||||
You appear to be running Vagrant outside of the official installers.
|
||||
Note that the installers are what ensure that Vagrant has all required
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
require File.expand_path("../../../base", __FILE__)
|
||||
|
||||
require "vagrant/util/experimental"
|
||||
|
||||
describe Vagrant::Util::Experimental do
|
||||
include_context "unit"
|
||||
before(:each) { described_class.reset! }
|
||||
subject { described_class }
|
||||
|
||||
describe "#enabled?" do
|
||||
it "returns true if enabled with '1'" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("1")
|
||||
expect(subject.enabled?).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if enabled with a list of features" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("list,of,features")
|
||||
expect(subject.enabled?).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if disabled" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("0")
|
||||
expect(subject.enabled?).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if not set" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return(nil)
|
||||
expect(subject.enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#global_enabled?" do
|
||||
it "returns true if enabled with '1'" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("1")
|
||||
expect(subject.global_enabled?).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if enabled with a partial list of features" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("list,of,features")
|
||||
expect(subject.global_enabled?).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if disabled" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("0")
|
||||
expect(subject.global_enabled?).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if not set" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return(nil)
|
||||
expect(subject.global_enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#feature_enabled?" do
|
||||
it "returns true if flag set to 1" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("1")
|
||||
expect(subject.feature_enabled?("anything")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if flag contains feature requested" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("secret_feature")
|
||||
expect(subject.feature_enabled?("secret_feature")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if flag contains feature requested and the request is a symbol" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("secret_feature")
|
||||
expect(subject.feature_enabled?(:secret_feature)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if flag contains feature requested with other features 'enabled'" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("secret_feature,other_secret")
|
||||
expect(subject.feature_enabled?("secret_feature")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if flag is set but does not contain feature requested" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("fake_feature")
|
||||
expect(subject.feature_enabled?("secret_feature")).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if flag set to 0" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("0")
|
||||
expect(subject.feature_enabled?("anything")).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if flag is not set" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return(nil)
|
||||
expect(subject.feature_enabled?("anything")).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#features_requested" do
|
||||
it "returns an array of requested features" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("secret_feature,other_secret")
|
||||
expect(subject.features_requested).to eq(["secret_feature","other_secret"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#guard_with" do
|
||||
it "does not execute the block if the feature is not requested" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return(nil)
|
||||
expect{|b| subject.guard_with("secret_feature", &b) }.not_to yield_control
|
||||
end
|
||||
|
||||
it "executes the block if the feature is valid and requested" do
|
||||
allow(ENV).to receive(:[]).with("VAGRANT_EXPERIMENTAL").and_return("secret_feature,other_secret")
|
||||
expect{|b| subject.guard_with("secret_feature", &b) }.to yield_control
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue