nugrant 2.0.0.dev2 → 2.0.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +6 -14
- data/.gitignore +2 -1
- data/.travis.yml +2 -2
- data/CHANGELOG.md +148 -3
- data/Gemfile +8 -20
- data/README.md +266 -72
- data/Rakefile +1 -0
- data/lib/nugrant.rb +14 -6
- data/lib/nugrant/bag.rb +116 -62
- data/lib/nugrant/helper/bag.rb +19 -19
- data/lib/nugrant/helper/env/exporter.rb +208 -0
- data/lib/nugrant/helper/env/namer.rb +47 -0
- data/lib/nugrant/helper/parameters.rb +12 -0
- data/lib/nugrant/helper/stack.rb +86 -0
- data/lib/nugrant/mixin/parameters.rb +98 -0
- data/lib/nugrant/parameters.rb +14 -68
- data/lib/nugrant/vagrant/errors.rb +27 -0
- data/lib/nugrant/vagrant/v2/command/env.rb +101 -0
- data/lib/nugrant/vagrant/v2/command/helper.rb +30 -0
- data/lib/nugrant/vagrant/v2/command/parameters.rb +16 -4
- data/lib/nugrant/vagrant/v2/command/restricted_keys.rb +60 -0
- data/lib/nugrant/vagrant/v2/command/root.rb +12 -2
- data/lib/nugrant/vagrant/v2/config/user.rb +9 -21
- data/lib/nugrant/vagrant/v2/plugin.rb +0 -1
- data/lib/nugrant/version.rb +1 -1
- data/locales/en.yml +13 -0
- data/nugrant.gemspec +3 -7
- data/test/lib/nugrant/helper/env/test_exporter.rb +238 -0
- data/test/lib/nugrant/helper/test_bag.rb +16 -0
- data/test/lib/nugrant/helper/test_parameters.rb +17 -0
- data/test/lib/nugrant/helper/test_stack.rb +152 -0
- data/test/lib/nugrant/test_bag.rb +132 -22
- data/test/lib/nugrant/test_config.rb +95 -92
- data/test/lib/nugrant/test_parameters.rb +232 -177
- data/test/lib/test_helper.rb +3 -0
- data/test/resources/json/params_user_nil_values.json +9 -0
- data/test/resources/vagrantfiles/v2.defaults_mixed_string_symbols +18 -0
- data/test/resources/vagrantfiles/v2.defaults_null_values_in_vagrantuser +23 -0
- data/test/resources/vagrantfiles/v2.defaults_using_string +18 -0
- data/test/resources/vagrantfiles/v2.defaults_using_symbol +18 -0
- data/test/resources/{Vagrantfile.v2.empty → vagrantfiles/v2.empty} +0 -2
- data/test/resources/{Vagrantfile.v2.fake → vagrantfiles/v2.fake} +4 -3
- data/test/resources/vagrantfiles/v2.missing_parameter +3 -0
- data/test/resources/{Vagrantfile.v2.real → vagrantfiles/v2.real} +0 -2
- data/test/resources/yaml/params_user_nil_values.yml +5 -0
- metadata +55 -88
- data/lib/nugrant/vagrant/v1/command/parameters.rb +0 -134
- data/lib/nugrant/vagrant/v1/command/root.rb +0 -81
- data/lib/nugrant/vagrant/v1/config/user.rb +0 -37
- data/lib/nugrant/vagrant/v1/plugin.rb +0 -6
- data/lib/vagrant_init.rb +0 -2
- data/test/resources/Vagrantfile.v1.empty +0 -2
- data/test/resources/Vagrantfile.v1.fake +0 -10
- data/test/resources/Vagrantfile.v1.real +0 -19
@@ -0,0 +1,47 @@
|
|
1
|
+
module Nugrant
|
2
|
+
module Helper
|
3
|
+
module Env
|
4
|
+
##
|
5
|
+
# A namer is a lambda taking as argument an array of segments
|
6
|
+
# that should return a string representation of those segments.
|
7
|
+
# How the segments are transformed to a string is up to the
|
8
|
+
# namer. By using various namer, we can change how a bag key
|
9
|
+
# is transformed into and environment variable name. This is
|
10
|
+
# like the strategy pattern.
|
11
|
+
#
|
12
|
+
module Namer
|
13
|
+
|
14
|
+
##
|
15
|
+
# Returns the default namer, which join segments together
|
16
|
+
# using a character and upcase the result.
|
17
|
+
#
|
18
|
+
# @param `char` The character used to join segments together, default to `"_"`.
|
19
|
+
#
|
20
|
+
# @return A lambda that will simply joins segment using the `char` argument
|
21
|
+
# and upcase the result.
|
22
|
+
#
|
23
|
+
def self.default(char = "_")
|
24
|
+
lambda do |segments|
|
25
|
+
segments.join(char).upcase()
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Returns the prefix namer, which add a prefix to segments
|
31
|
+
# and delegate its work to another namer.
|
32
|
+
#
|
33
|
+
# @param prefix The prefix to add to segments.
|
34
|
+
# @param delegate_namer A namer that will be used to transform the prefixed segments.
|
35
|
+
#
|
36
|
+
# @return A lambda that will simply add prefix to segments and will call
|
37
|
+
# the delegate_namer with those new segments.
|
38
|
+
#
|
39
|
+
def self.prefix(prefix, delegate_namer)
|
40
|
+
lambda do |segments|
|
41
|
+
delegate_namer.call([prefix] + segments)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Nugrant
|
2
|
+
module Helper
|
3
|
+
class Stack
|
4
|
+
@@DEFAULT_MATCHER = /^(.+):([0-9]+)/
|
5
|
+
|
6
|
+
def self.fetch_error_region(stack, options = {})
|
7
|
+
entry = find_entry(stack, options)
|
8
|
+
location = extract_error_location(entry, options)
|
9
|
+
|
10
|
+
return (options[:unknown] || "Unknown") if not location[:file] and not location[:line]
|
11
|
+
return location[:file] if not location[:line]
|
12
|
+
|
13
|
+
fetch_error_region_from_location(location, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.fetch_error_region_from_location(location, options = {})
|
17
|
+
prefix = options[:prefix] || " "
|
18
|
+
width = options[:width] || 4
|
19
|
+
file = File.new(location[:file], "r")
|
20
|
+
line = location[:line]
|
21
|
+
|
22
|
+
index = 0
|
23
|
+
|
24
|
+
lines = []
|
25
|
+
while (line_string = file.gets())
|
26
|
+
index += 1
|
27
|
+
next if (line - index).abs > width
|
28
|
+
|
29
|
+
line_prefix = "#{prefix}#{index}:"
|
30
|
+
line_prefix += (line == index ? ">> " : " ")
|
31
|
+
|
32
|
+
lines << "#{line_prefix}#{line_string}"
|
33
|
+
end
|
34
|
+
|
35
|
+
lines.join().chomp()
|
36
|
+
rescue
|
37
|
+
return (options[:unknown] || "Unknown") if not location[:file] and not location[:line]
|
38
|
+
return location[:file] if not location[:line]
|
39
|
+
|
40
|
+
"#{location[:file]}:#{location[:line]}"
|
41
|
+
ensure
|
42
|
+
file.close() if file
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Search a stack list (as simple string array) for the first
|
47
|
+
# entry that match the +:matcher+.
|
48
|
+
#
|
49
|
+
def self.find_entry(stack, options = {})
|
50
|
+
matcher = options[:matcher] || @@DEFAULT_MATCHER
|
51
|
+
|
52
|
+
stack.find do |entry|
|
53
|
+
entry =~ matcher
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Extract error location information from a stack entry using the
|
59
|
+
# matcher received in arguments.
|
60
|
+
#
|
61
|
+
# The usual stack entry format is:
|
62
|
+
# > /home/users/joe/work/lib/ruby.rb:4:Error message
|
63
|
+
#
|
64
|
+
# This function will extract the file and line information from
|
65
|
+
# the stack entry using the matcher. The matcher is expected to
|
66
|
+
# have two groups, the first for the file and the second for
|
67
|
+
# line.
|
68
|
+
#
|
69
|
+
# The results is returned in form of a hash with two keys, +:file+
|
70
|
+
# for the file information and +:line+ for the line information.
|
71
|
+
#
|
72
|
+
# If the matcher matched zero group, return +{:file => nil, :line => nil}+.
|
73
|
+
# If the matcher matched one group, return +{:file => file, :line => nil}+.
|
74
|
+
# If the matcher matched two groups, return +{:file => file, :line => line}+.
|
75
|
+
#
|
76
|
+
def self.extract_error_location(entry, options = {})
|
77
|
+
matcher = options[:matcher] || @@DEFAULT_MATCHER
|
78
|
+
|
79
|
+
result = matcher.match(entry)
|
80
|
+
captures = result ? result.captures : []
|
81
|
+
|
82
|
+
{:file => captures[0], :line => captures[1] ? captures[1].to_i() : nil}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Nugrant
|
2
|
+
module Mixin
|
3
|
+
##
|
4
|
+
# Mixin module so it's possible to share parameters
|
5
|
+
# logic between default Parameters class and Vagrant
|
6
|
+
# implementation.
|
7
|
+
#
|
8
|
+
# This method delegates method missing to the overall
|
9
|
+
# bag instance. This means that even if the class
|
10
|
+
# including this module doesn't inherit Bag directly,
|
11
|
+
# it act exactly like one.
|
12
|
+
#
|
13
|
+
# To initialize the mixin module correctly, you must call
|
14
|
+
# the compute_bags! method at least once to initialize
|
15
|
+
# all variables. You should make this call in including
|
16
|
+
# class' constructor directly.
|
17
|
+
#
|
18
|
+
module Parameters
|
19
|
+
def method_missing(method, *args, &block)
|
20
|
+
case
|
21
|
+
when @__all.class.method_defined?(method)
|
22
|
+
@__all.send(method, *args, &block)
|
23
|
+
else
|
24
|
+
@__all[method]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def defaults()
|
29
|
+
@__defaults
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Set the new default values for the
|
34
|
+
# various parameters contain by this instance.
|
35
|
+
# This will call __compute_all() to recompute
|
36
|
+
# correct precedences.
|
37
|
+
#
|
38
|
+
# =| Attributes
|
39
|
+
# * +elements+ - The new default elements
|
40
|
+
#
|
41
|
+
def defaults=(elements)
|
42
|
+
@__defaults = Bag.new(elements, @__options)
|
43
|
+
|
44
|
+
# When defaults change, we need to recompute parameters hierarchy
|
45
|
+
compute_all!(@__options)
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Compute all parameters bags (current, user, system, default and all).
|
50
|
+
#
|
51
|
+
# =| Arguments
|
52
|
+
# * `config`
|
53
|
+
# The configuration object used to determine where to find the various
|
54
|
+
# bag source data. This can be either directly a `Nugrant::Config`
|
55
|
+
# object or a hash that will be pass to `Nugrant::Config` constructor.
|
56
|
+
#
|
57
|
+
# * `options`
|
58
|
+
# An options hash where some customization option can be passed.
|
59
|
+
# Defaults to an empty hash, see options for specific option default
|
60
|
+
# values.
|
61
|
+
#
|
62
|
+
# =| Options
|
63
|
+
# * `:defaults`
|
64
|
+
# A hash that is used as the initial data for the defaults bag. Defaults
|
65
|
+
# to an empty hash.
|
66
|
+
#
|
67
|
+
# * `:key_error`
|
68
|
+
# This option is passed to Bag.new constructor in it's options hash. See
|
69
|
+
# Bag.new for details on this options.
|
70
|
+
#
|
71
|
+
def compute_bags!(config, options = {})
|
72
|
+
config = config.kind_of?(Nugrant::Config) ? config : Nugrant::Config.new(config)
|
73
|
+
|
74
|
+
@__options = options
|
75
|
+
|
76
|
+
@__current = Helper::Bag.read(config.current_path, config.params_format, options)
|
77
|
+
@__user = Helper::Bag.read(config.user_path, config.params_format, options)
|
78
|
+
@__system = Helper::Bag.read(config.system_path, config.params_format, options)
|
79
|
+
@__defaults = Bag.new(options[:defaults] || {}, options)
|
80
|
+
|
81
|
+
compute_all!(options)
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Recompute the correct precedences by merging the various
|
86
|
+
# bag in the right order and return the result as a Nugrant::Bag
|
87
|
+
# object.
|
88
|
+
#
|
89
|
+
def compute_all!(options = {})
|
90
|
+
@__all = Bag.new({}, options)
|
91
|
+
@__all.merge!(@__defaults)
|
92
|
+
@__all.merge!(@__system)
|
93
|
+
@__all.merge!(@__user)
|
94
|
+
@__all.merge!(@__current)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/nugrant/parameters.rb
CHANGED
@@ -1,87 +1,33 @@
|
|
1
1
|
require 'nugrant/bag'
|
2
2
|
require 'nugrant/config'
|
3
3
|
require 'nugrant/helper/bag'
|
4
|
+
require 'nugrant/mixin/parameters'
|
4
5
|
|
5
6
|
module Nugrant
|
6
7
|
class Parameters
|
7
|
-
attr_reader :__current, :__user, :__system, :__defaults, :__all
|
8
|
-
|
9
8
|
##
|
10
9
|
# Create a new parameters object which holds completed
|
11
10
|
# merged values. The following precedence is used to decide
|
12
11
|
# which location has precedence over which location:
|
13
12
|
#
|
14
13
|
# (Highest) ------------------ (Lowest)
|
15
|
-
#
|
14
|
+
# project < user < system < defaults
|
16
15
|
#
|
17
|
-
# =|
|
18
|
-
# *
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
16
|
+
# =| Arguments
|
17
|
+
# * `config`
|
18
|
+
# A hash that will be passed to Nugrant::Config.new() or
|
19
|
+
# a Nugrant::Config instance directly.
|
20
|
+
# See Nugrant::Config constructor for options that you can use.
|
22
21
|
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@__user = Helper::Bag.read(@__config.user_path, @__config.params_format)
|
28
|
-
@__system = Helper::Bag.read(@__config.system_path, @__config.params_format)
|
29
|
-
@__defaults = Bag.new(options[:defaults] || {})
|
30
|
-
|
31
|
-
__compute_all()
|
32
|
-
end
|
33
|
-
|
34
|
-
def [](key)
|
35
|
-
return @__all[key]
|
36
|
-
end
|
37
|
-
|
38
|
-
def method_missing(method, *args, &block)
|
39
|
-
return @__all[method]
|
40
|
-
end
|
41
|
-
|
42
|
-
def empty?()
|
43
|
-
@__all.empty?()
|
44
|
-
end
|
45
|
-
|
46
|
-
def has?(key)
|
47
|
-
return @__all.has?(key)
|
48
|
-
end
|
49
|
-
|
50
|
-
def each(&block)
|
51
|
-
@__all.each(&block)
|
52
|
-
end
|
53
|
-
|
54
|
-
##
|
55
|
-
# Set the new default values for the
|
56
|
-
# various parameters contain by this instance.
|
57
|
-
# This will call __compute_all() to recompute
|
58
|
-
# correct precedences.
|
59
|
-
#
|
60
|
-
# =| Attributes
|
61
|
-
# * +elements+ - The new default elements
|
22
|
+
# * `options`
|
23
|
+
# An options hash that is passed to Mixin::Parameters.compute_bags! method.
|
24
|
+
# See Mixin::Parameters.compute_bags! for details on the various options
|
25
|
+
# available.
|
62
26
|
#
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
# When defaults change, we need to recompute parameters hierarchy
|
67
|
-
__compute_all()
|
27
|
+
def initialize(config, options = {})
|
28
|
+
compute_bags!(config, options)
|
68
29
|
end
|
69
30
|
|
70
|
-
|
71
|
-
# Recompute the correct precedences by merging the various
|
72
|
-
# bag in the right order and return the result as a Nugrant::Bag
|
73
|
-
# object.
|
74
|
-
#
|
75
|
-
def __compute_all()
|
76
|
-
@__all = Bag.new()
|
77
|
-
@__all.__merge!(@__defaults)
|
78
|
-
@__all.__merge!(@__system)
|
79
|
-
@__all.__merge!(@__user)
|
80
|
-
@__all.__merge!(@__current)
|
81
|
-
end
|
82
|
-
|
83
|
-
def __to_hash()
|
84
|
-
@__all.__to_hash()
|
85
|
-
end
|
31
|
+
include Mixin::Parameters
|
86
32
|
end
|
87
33
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'vagrant/errors'
|
2
|
+
|
3
|
+
require 'nugrant/helper/stack'
|
4
|
+
|
5
|
+
module Nugrant
|
6
|
+
module Vagrant
|
7
|
+
module Errors
|
8
|
+
class NugrantVagrantError < ::Vagrant::Errors::VagrantError
|
9
|
+
error_namespace("nugrant.vagrant.errors")
|
10
|
+
end
|
11
|
+
|
12
|
+
class ParameterNotFoundError < NugrantVagrantError
|
13
|
+
error_key(:parameter_not_found)
|
14
|
+
|
15
|
+
def initialize(options = nil, *args)
|
16
|
+
super({:context => compute_context()}.merge(options || {}), *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def compute_context()
|
20
|
+
Helper::Stack.fetch_error_region(caller(), {
|
21
|
+
:matcher => /(.+Vagrantfile):([0-9]+)/
|
22
|
+
})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'nugrant'
|
2
|
+
require 'nugrant/helper/env/exporter'
|
3
|
+
require 'nugrant/parameters'
|
4
|
+
|
5
|
+
EnvExporter = Nugrant::Helper::Env::Exporter
|
6
|
+
|
7
|
+
module Nugrant
|
8
|
+
module Vagrant
|
9
|
+
module V2
|
10
|
+
module Command
|
11
|
+
class Env < ::Vagrant.plugin("2", :command)
|
12
|
+
def initialize(arguments, environment)
|
13
|
+
super(arguments, environment)
|
14
|
+
|
15
|
+
@unset = false
|
16
|
+
@format = :terminal
|
17
|
+
@show_help = false
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_parser()
|
21
|
+
return OptionParser.new do |parser|
|
22
|
+
parser.banner = "Usage: vagrant user env [<options>]"
|
23
|
+
parser.separator ""
|
24
|
+
|
25
|
+
parser.separator "Outputs the commands that should be executed to export\n" +
|
26
|
+
"the various parameter as environment variables. By default,\n" +
|
27
|
+
"existing ones are overridden. The --format argument can be used\n" +
|
28
|
+
"to choose in which format the variables should be displayed.\n" +
|
29
|
+
"Changing the format will also change where they are displayed.\n"
|
30
|
+
parser.separator ""
|
31
|
+
|
32
|
+
parser.separator "Available formats:"
|
33
|
+
parser.separator " autoenv => Write commands to a file named `.env` in the current directory.\n" +
|
34
|
+
" See https://github.com/kennethreitz/autoenv for more info."
|
35
|
+
parser.separator " terminal => Display commands to terminal so they can be sourced."
|
36
|
+
parser.separator " script => Write commands to a bash script named `nugrant2env.sh` so it can be sourced."
|
37
|
+
parser.separator ""
|
38
|
+
|
39
|
+
parser.separator "Available options:"
|
40
|
+
parser.separator ""
|
41
|
+
|
42
|
+
parser.on("-u", "--[no-]unset", "Generates commands needed to unset environment variables, default false") do |unset|
|
43
|
+
@unset = unset
|
44
|
+
end
|
45
|
+
|
46
|
+
parser.on("-f", "--format FORMAT", "Determines in what format variables are output, default to terminal") do |format|
|
47
|
+
@format = format.to_sym()
|
48
|
+
end
|
49
|
+
|
50
|
+
parser.on("-h", "--help", "Print this help") do
|
51
|
+
@show_help = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def error(message, parser)
|
57
|
+
@env.ui.info("ERROR: #{message}", :prefix => false)
|
58
|
+
@env.ui.info("", :prefix => false)
|
59
|
+
|
60
|
+
help(parser)
|
61
|
+
|
62
|
+
return 1
|
63
|
+
end
|
64
|
+
|
65
|
+
def help(parser)
|
66
|
+
@env.ui.info(parser.help, :prefix => false)
|
67
|
+
end
|
68
|
+
|
69
|
+
def execute
|
70
|
+
parser = create_parser()
|
71
|
+
arguments = parse_options(parser)
|
72
|
+
|
73
|
+
return error("Invalid format value '#{@format}'", parser) if not EnvExporter.valid?(@format)
|
74
|
+
return help(parser) if @show_help
|
75
|
+
|
76
|
+
@logger.debug("Nugrant 'Env'")
|
77
|
+
with_target_vms(arguments) do |vm|
|
78
|
+
config = vm.config.user
|
79
|
+
parameters = config ? config : Nugrant::Parameters.new()
|
80
|
+
bag = parameters.__all
|
81
|
+
|
82
|
+
options = {:type => @unset ? :unset : :export}
|
83
|
+
|
84
|
+
case
|
85
|
+
when @format == :script
|
86
|
+
EnvExporter.script_exporter(bag, options)
|
87
|
+
when @format == :autoenv
|
88
|
+
EnvExporter.autoenv_exporter(bag, options)
|
89
|
+
when @format == :terminal
|
90
|
+
EnvExporter.terminal_exporter(bag, options)
|
91
|
+
end
|
92
|
+
|
93
|
+
# No need to execute for the other VMs
|
94
|
+
return 0
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|