From be5964a1db53c52b907cae40cf301054abfdaf74 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 21 Aug 2019 14:44:16 -0700 Subject: [PATCH] Add basic provisioner sorting --- .../action/builtin/mixin_provisioners.rb | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/lib/vagrant/action/builtin/mixin_provisioners.rb b/lib/vagrant/action/builtin/mixin_provisioners.rb index 5c17556ad..af7c3ddcb 100644 --- a/lib/vagrant/action/builtin/mixin_provisioners.rb +++ b/lib/vagrant/action/builtin/mixin_provisioners.rb @@ -37,14 +37,84 @@ module Vagrant [result, options] end + @_provisioner_instances = sort_provisioner_instances(@_provisioner_instances) return @_provisioner_instances.compact end # Sorts provisioners based on order specified with before/after options # + # TODO: make sure all defined provisioners work here (i.e. even thoughs defined in separate but loaded Vagrantfile) + # # @return [Array] def sort_provisioner_instances(pvs) - return pvs + final_provs = [] + root_provs = [] + dep_provs = [] + each_provs = [] + all_provs = [] + + # extract root provisioners + root_provs = pvs.map { |p,o| [p,o] if o[:before].nil? && o[:after].nil? }.reject(&:nil?) + # extract dependency provisioners + dep_provs = pvs.map { |p,o| [p,o] if (!o[:before].nil? && !o[:before].is_a?(Symbol)) || (!o[:after].nil? && !o[:after].is_a?(Symbol)) }.reject(&:nil?) + # extract each provisioners + each_provs = pvs.map { |p,o| [p,o] if o[:before] == :each || o[:after] == :each }.reject(&:nil?) + # extract all provisioners + all_provs = pvs.map { |p,o| [p,o] if o[:before] == :all || o[:after] == :all }.reject(&:nil?) + + if root_provs.size == pvs.size + # no dependencies found + return pvs + end + + # TODO: Log here, that provisioner order is being changed + + # insert provisioners in order + final_provs = root_provs + dep_provs.each do |p,options| + if options[:before] + idx = final_provs.each_with_index.map { |(p,o), i| i if o[:name].to_s == options[:before] }.reject(&:nil?).first + idx -= 1 unless idx == 0 + final_provs.insert(idx, [p, options]) + elsif options[:after] + idx = final_provs.each_with_index.map { |(p,o), i| i if o[:name].to_s == options[:after] }.reject(&:nil?).first + idx += 1 + final_provs.insert(idx, [p, options]) + end + end + + # add each to final array + tmp_final_provs = final_provs.dup + extra_index = 0 + each_provs.reverse_each do |p,options| + final_provs.each_with_index.map do |(prv,o), i| + if options[:before] + idx = i-1 unless idx == 0 + idx += extra_index + extra_index += 1 + tmp_final_provs.insert(idx, [p,options]) + elsif options[:after] + idx = i+1 + idx += extra_index + extra_index += 1 + tmp_final_provs.insert(idx, [p,options]) + end + end + end + final_provs = tmp_final_provs + + # add all to final array + tmp_final_provs = final_provs.dup + all_provs.reverse_each do |p,options| + if options[:before] + tmp_final_provs.insert(0, [p,options]) + elsif options[:after] + tmp_final_provs.push([p,options]) + end + end + final_provs = tmp_final_provs + + return final_provs end # This will return a mapping of a provisioner instance to its