require 'spec_helper' require 'r10k/action/base' require 'puppet_forge/connection' require 'r10k/action/runner' describe R10K::Action::Runner do let(:action_class) do Class.new do attr_reader :opts attr_reader :argv def initialize(opts, argv, settings = {}) @opts = opts @argv = argv @settings = {} end def call @argv.map(&:upcase) end end end subject(:runner) { described_class.new({:opts => :yep}, %w[args yes], action_class) } before(:each) do expect(runner.logger).not_to receive(:error) end describe "instantiating the wrapped class" do it "creates an instance of the class" do expect(runner.instance).to be_a_kind_of action_class end it "passes the opts and argv to the instance" do expect(runner.instance.opts).to eq(:opts => :yep) expect(runner.instance.argv).to eq(%w[args yes]) end it "strips out options that the runner handles" do runner = described_class.new({:opts => :yep, :loglevel => 'FATAL'}, %w[args yes], action_class) expect(runner.instance.opts).to eq(:opts => :yep) end end describe "calling" do it "configures logging" do expect(runner).to receive(:setup_logging) runner.call end it "configures settings" do expect(runner).to receive(:setup_settings) runner.call end it "configures forge authorization" do expect(runner).to receive(:setup_authorization) runner.call end it "returns the result of the wrapped class #call method" do expect(runner.call).to eq %w[ARGS YES] end end describe "configuring settings" do subject(:runner) { described_class.new(options, %w[args yes], action_class) } let(:global_settings) { R10K::Settings.global_settings } before(:each) do expect(R10K::Settings).to receive(:global_settings).and_return(global_settings) allow(File).to receive(:executable?).and_return(true) end opts = { cachedir: nil, puppet_path: :deploy, generate_types: :deploy, } opts.each do |opt, conf_path| context "with #{opt} config setting" do let(:options) { { config: "spec/fixtures/unit/action/r10k_#{opt}.yaml" } } context "when not overridden" do it "uses the config value" do override = { "#{opt}": "/config_#{opt}" } overrides = if conf_path.nil? override else { "#{conf_path}": override } end expect(global_settings).to receive(:evaluate).with(hash_including(overrides)).and_call_original runner.call end end context "when overridden" do let(:options) { super().merge("#{opt.to_s.sub('_','-')}": "/overridden_#{opt}") } it "uses the overridden value" do override = { "#{opt}": "/overridden_#{opt}" } overrides = if conf_path.nil? override else { "#{conf_path}": override } end expect(global_settings).to receive(:evaluate).with(hash_including(overrides)).and_call_original runner.call end end end context "with complete config" do let(:options) { { config: "spec/fixtures/unit/action/r10k.yaml" } } let(:config) do config = {} opts.each do |o, path| if path.nil? config[o] = "/config_#{o}" else config[path] ||= {} config[path][o] = "/config_#{o}" end end config end context "when not overridden" do it "uses the config value" do expect(global_settings).to receive(:evaluate).with(config).and_call_original runner.call end end context "when overridden" do let(:options) { super().merge("#{opt.to_s.sub('_','-')}": "/overridden_#{opt}") } it "uses the overridden value" do with_overrides = config if conf_path.nil? with_overrides[opt] = "/overridden_#{opt}" else with_overrides[conf_path][opt] = "/overridden_#{opt}" end expect(global_settings).to receive(:evaluate).with(with_overrides).and_call_original runner.call end end end end end describe "configuring logging" do it "sets the log level if :loglevel is provided" do runner = described_class.new({:opts => :yep, :loglevel => 'FATAL'}, %w[args yes], action_class) expect(R10K::Logging).to receive(:level=).with('FATAL') runner.call end it "does not modify the loglevel if :loglevel is not provided" do expect(R10K::Logging).to_not receive(:level=) runner.call end end describe "configuration authorization" do context "when license is not present" do before(:each) do expect(R10K::Util::License).to receive(:load).and_return(nil) end it "does not set authorization header on connection class" do expect(PuppetForge::Connection).not_to receive(:authorization=) runner.setup_authorization end end context "when license is present but invalid" do before(:each) do expect(R10K::Util::License).to receive(:load).and_raise(R10K::Error.new('invalid license')) end it "issues warning to logger" do expect(runner.logger).to receive(:warn).with(/invalid license/) runner.setup_authorization end it "does not set authorization header on connection class" do expect(PuppetForge::Connection).not_to receive(:authorization=) runner.setup_authorization end end context "when license is present and valid" do before(:each) do mock_license = double('pe-license', :authorization_token => 'test token') expect(R10K::Util::License).to receive(:load).and_return(mock_license) end it "sets authorization header on connection class" do expect(PuppetForge::Connection).to receive(:authorization=).with('test token') runner.setup_authorization end end end end