require 'json' module VagrantPlugins module Salt class Provisioner < Vagrant.plugin("2", :provisioner) # Default path values to set within configuration only # if configuration value is unset and local path exists OPTIMISTIC_PATH_DEFAULTS = Hash[*[ "minion_config", "salt/minion", "minion_key", "salt/key/minion.key", "minion_pub", "salt/key/minion.pub", "master_config", "salt/master", "master_key", "salt/key/master.key", "master_pub", "salt/key/master.pub" ].map(&:freeze)].freeze def provision set_default_configs upload_configs upload_keys run_bootstrap_script call_overstate call_highstate call_orchestrate end # Return a list of accepted keys def keys(group='minions') out = @machine.communicate.sudo("salt-key --out json") do |type, output| begin if type == :stdout out = JSON::load(output) break out[group] end end end return out end ## Utilities def expanded_path(rel_path) Pathname.new(rel_path).expand_path(@machine.env.root_path) end def binaries_found ## Determine States, ie: install vs configure desired_binaries = [] if !@config.no_minion if @machine.config.vm.communicator == :winrm desired_binaries.push('C:\\salt\\salt-minion.bat') desired_binaries.push('C:\\salt\\salt-call.bat') else desired_binaries.push('salt-minion') desired_binaries.push('salt-call') end end if @config.install_master if @machine.config.vm.communicator == :winrm raise Vagrant::Errors::ProvisionerWinRMUnsupported, name: "salt.install_master" else desired_binaries.push('salt-master') end end if @config.install_syndic if @machine.config.vm.communicator == :winrm raise Vagrant::Errors::ProvisionerWinRMUnsupported, name: "salt.install_syndic" else desired_binaries.push('salt-syndic') end end found = true for binary in desired_binaries @machine.env.ui.info "Checking if %s is installed" % binary if !@machine.communicate.test("which %s" % binary) @machine.env.ui.info "%s was not found." % binary found = false else @machine.env.ui.info "%s found" % binary end end return found end def need_configure @config.minion_config or @config.minion_key or @config.master_config or @config.master_key or @config.grains_config or @config.version or @config.minion_json_config or @config.master_json_config end def need_install if @config.always_install return true else return !binaries_found() end end def temp_config_dir if @machine.config.vm.communicator == :winrm return @config.temp_config_dir || "C:\\tmp" else return @config.temp_config_dir || "/tmp" end end # Generates option string for bootstrap script def bootstrap_options(install, configure, config_dir) # Any extra options passed to bootstrap if @config.bootstrap_options options = @config.bootstrap_options else options = "" end if @config.master_json_config && @machine.config.vm.communicator != :winrm config = @config.master_json_config options = "%s -J '#{config}'" % [options] end if @config.minion_json_config && @machine.config.vm.communicator != :winrm config = @config.minion_json_config options = "%s -j '#{config}'" % [options] end if configure && @machine.config.vm.communicator != :winrm options = "%s -F -c %s" % [options, config_dir] end if @config.seed_master && @config.install_master && @machine.config.vm.communicator != :winrm seed_dir = "/tmp/minion-seed-keys" @machine.communicate.sudo("mkdir -p -m777 #{seed_dir}") @config.seed_master.each do |name, keyfile| sourcepath = expanded_path(keyfile).to_s dest = "#{seed_dir}/#{name}" @machine.communicate.upload(sourcepath, dest) end options = "#{options} -k #{seed_dir}" end if configure && !install && @machine.config.vm.communicator != :winrm options = "%s -C" % options end if @config.install_master && @machine.config.vm.communicator != :winrm options = "%s -M" % options end if @config.install_syndic && @machine.config.vm.communicator != :winrm options = "%s -S" % options end if @config.no_minion && @machine.config.vm.communicator != :winrm options = "%s -N" % options end if @config.install_type && @machine.config.vm.communicator != :winrm options = "%s %s" % [options, @config.install_type] end if @config.install_args && @machine.config.vm.communicator != :winrm options = "%s %s" % [options, @config.install_args] end if @config.verbose @machine.env.ui.info "Using Bootstrap Options: %s" % options end return options end ## Actions # Get pillar string to pass with the salt command def get_pillar if !@config.pillar_data.empty? if @machine.config.vm.communicator == :winrm # ' doesn't have any special behavior on the command prompt, # so '{"x":"y"}' becomes '{x:y}' with literal single quotes. # However, """ will become " , and \\""" will become \" . # Use \\"" instead of \\""" for literal inner-value quotes # to avoid issue with odd number of quotes. # --% disables special PowerShell parsing on the rest of the line. " --% pillar=#{@config.pillar_data.to_json.gsub(/(?