\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef/embedded/lib/ruby/gems/2.7.0/gems/chef-16.3.45/spec/unit/application/

Viewing File: solo_spec.rb

#
# Author:: AJ Christensen (<aj@junglist.gen.nz>)
# Copyright:: Copyright (c) Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require "spec_helper"

describe Chef::Application::Solo do

  let(:app) { Chef::Application::Solo.new }

  before do
    allow(Kernel).to receive(:trap).and_return(:ok)
    allow(app).to receive(:configure_opt_parser).and_return(true)
    allow(app).to receive(:configure_chef).and_return(true)
    allow(app).to receive(:configure_logging).and_return(true)
    allow(app).to receive(:trap)
    allow(app).to receive(:cli_arguments).and_return([])

    Chef::Config[:json_attribs] = false
    Chef::Config[:solo] = true
    Chef::Config[:solo_legacy_mode] = true

    # protect the unit tests against accidental --delete-entire-chef-repo from firing
    # for real during tests.  DO NOT delete this line.
    expect(FileUtils).not_to receive(:rm_rf)
  end

  context "in legacy mode" do
    describe "configuring the application" do
      it "should call set_specific_recipes" do
        expect(app).to receive(:set_specific_recipes)
        app.reconfigure
      end

      it "should set solo mode to true" do
        app.reconfigure
        expect(Chef::Config[:solo]).to be_truthy
      end

      describe "when configured to not fork the client process" do
        before do
          Chef::Config[:client_fork] = false
          Chef::Config[:daemonize] = false
          Chef::Config[:interval] = nil
          Chef::Config[:splay] = nil
        end

        context "when interval is given" do
          before do
            Chef::Config[:interval] = 600
          end

          it "should terminate with message" do
            expect(Chef::Application).to receive(:fatal!).with(/interval runs are (disabled|not supported)/)
            app.reconfigure
          end
        end
      end

      describe "when in daemonized mode and no interval has been set", :unix_only do
        before do
          Chef::Config[:daemonize] = true
        end

        it "should set the interval to 1800" do
          Chef::Config[:interval] = nil
          app.reconfigure
          expect(Chef::Config[:interval]).to eq(1800)
        end
      end

      describe "when the json_attribs configuration option is specified" do
        let(:json_attribs) { { "a" => "b" } }
        let(:config_fetcher) { double(Chef::ConfigFetcher, fetch_json: json_attribs) }
        let(:json_source) { "https://foo.com/foo.json" }

        before do
          Chef::Config[:json_attribs] = json_source
          expect(Chef::ConfigFetcher).to receive(:new).with(json_source)
            .and_return(config_fetcher)
        end

        it "reads the JSON attributes from the specified source" do
          app.reconfigure
          expect(app.chef_client_json).to eq(json_attribs)
        end
      end

      it "downloads a tarball when the recipe_url configuration option is specified" do
        Chef::Config[:cookbook_path] = "#{Dir.tmpdir}/chef-solo/cookbooks"
        Chef::Config[:recipe_url] = "http://junglist.gen.nz/recipes.tgz"

        expect(FileUtils).to receive(:mkdir_p).with("#{Dir.tmpdir}/chef-solo").and_return(true)

        tarfile = StringIO.new("remote_tarball_content")
        target_file = StringIO.new

        expect(app).to receive(:open).with("http://junglist.gen.nz/recipes.tgz").and_yield(tarfile)
        expect(File).to receive(:open).with("#{Dir.tmpdir}/chef-solo/recipes.tgz", "wb").and_yield(target_file)

        archive = double(Mixlib::Archive)

        expect(Mixlib::Archive).to receive(:new).with("#{Dir.tmpdir}/chef-solo/recipes.tgz").and_return(archive)
        expect(archive).to receive(:extract).with("#{Dir.tmpdir}/chef-solo", { perms: false, ignore: /^\.$/ })
        app.reconfigure
        expect(target_file.string).to eq("remote_tarball_content")
      end

      it "fetches the recipe_url first when both json_attribs and recipe_url are specified" do
        json_attribs = { "a" => "b" }
        config_fetcher = instance_double("Chef::ConfigFetcher", fetch_json: json_attribs)

        Chef::Config[:json_attribs] = "https://foo.com/foo.json"
        Chef::Config[:recipe_url] = "http://icanhas.cheezburger.com/lolcats"
        Chef::Config[:cookbook_path] = "#{Dir.tmpdir}/chef-solo/cookbooks"
        expect(FileUtils).to receive(:mkdir_p).with("#{Dir.tmpdir}/chef-solo").and_return(true)

        archive = double(Mixlib::Archive)

        expect(Mixlib::Archive).to receive(:new).with("#{Dir.tmpdir}/chef-solo/recipes.tgz").and_return(archive)
        expect(archive).to receive(:extract).with("#{Dir.tmpdir}/chef-solo", { perms: false, ignore: /^\.$/ })
        expect(app).to receive(:fetch_recipe_tarball).ordered
        expect(Chef::ConfigFetcher).to receive(:new).ordered.and_return(config_fetcher)
        app.reconfigure
      end
    end

    describe "after the application has been configured" do
      before do
        Chef::Config[:solo] = true
        Chef::Config[:solo_legacy_mode] = true

        allow(Chef::Daemon).to receive(:change_privilege)
        chef_client = double("Chef::Client")
        allow(Chef::Client).to receive(:new).and_return(chef_client)
        # this is all stuff the reconfigure method needs
        allow(app).to receive(:configure_opt_parser).and_return(true)
        allow(app).to receive(:configure_chef).and_return(true)
        allow(app).to receive(:configure_logging).and_return(true)
      end

      it "should change privileges" do
        expect(Chef::Daemon).to receive(:change_privilege).and_return(true)
        app.setup_application
      end
    end

    it_behaves_like "an application that loads a dot d" do
      let(:dot_d_config_name) { :solo_d_dir }
    end
  end

  context "in local mode" do
    let(:root_path) { windows? ? "C:/var/chef" : "/var/chef" }

    before do
      Chef::Config[:solo_legacy_mode] = false
    end

    it "sets solo mode to true" do
      app.reconfigure
      expect(Chef::Config[:solo]).to be_truthy
    end

    it "sets local mode to true" do
      app.reconfigure
      expect(Chef::Config[:local_mode]).to be_truthy
    end

    context "argv gets tidied up" do
      before do
        @original_argv = ARGV.dup
        ARGV.clear
        Chef::Config[:treat_deprecation_warnings_as_errors] = false
      end

      after do
        ARGV.replace(@original_argv)
      end

      it "deletes --ez" do
        ARGV << "--ez"
        app.reconfigure
        expect(ARGV.include?("--ez")).to be_falsey
      end
    end

    it "sets the repo path" do
      expect(Chef::Config).to receive(:find_chef_repo_path).and_return(root_path)
      app.reconfigure
      expect(Chef::Config.key?(:chef_repo_path)).to be_truthy
      expect(Chef::Config[:chef_repo_path]).to eq (root_path)
    end

    it "runs chef-client in local mode" do
      allow(app).to receive(:setup_application).and_return(true)
      allow(app).to receive(:run_application).and_return(true)
      allow(app).to receive(:configure_chef).and_return(true)
      allow(app).to receive(:configure_logging).and_return(true)
      expect(Chef::Application::Client).to receive_message_chain(:new, :run)
      app.run
    end

  end
end