# # Copyright:: Copyright (c) 2017 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" require "chef-cli/policyfile/chef_server_lock_fetcher" describe ChefCLI::Policyfile::ChefServerLockFetcher do let(:revision_id) { "6fe753184c8946052d3231bb4212116df28d89a3a5f7ae52832ad408419dd5eb" } let(:identifier) { "fab501cfaf747901bd82c1bc706beae7dc3a350c" } let(:minimal_lockfile_json) do <<~E { "revision_id": "#{revision_id}", "name": "install-example", "run_list": [ "recipe[local-cookbook::default]" ], "cookbook_locks": { "local-cookbook": { "version": "2.3.4", "identifier": "#{identifier}", "dotted_decimal_identifier": "70567763561641081.489844270461035.258281553147148", "source": "cookbooks/local-cookbook", "cache_key": null, "scm_info": null, "source_options": { "path": "cookbooks/local-cookbook" } } }, "default_attributes": {}, "override_attributes": {}, "solution_dependencies": { "Policyfile": [ [ "local-cookbook", ">= 0.0.0" ] ], "dependencies": { "local-cookbook (2.3.4)": [ ] } } } E end def minimal_lockfile FFI_Yajl::Parser.parse(minimal_lockfile_json) end let(:policy_name) { "chatserver" } let(:policy_revision_id) { "somerevisionid" } let(:policy_group) { "somegroup" } let(:url) { "https://chef.example/organizations/monkeynews" } let(:chef_config) do double("ChefConfig").tap do |double| allow(double).to receive(:client_key).and_return("key") allow(double).to receive(:node_name).and_return("node_name") end end let(:http_client) { instance_double("Chef::ServerAPI", url: url ) } let(:minimal_lockfile_modified) do minimal_lockfile.tap do |lockfile| lockfile["cookbook_locks"]["local-cookbook"]["source_options"] = { "chef_server_artifact" => url, "identifier" => identifier, } end end subject(:fetcher) { described_class.new(policy_name, source_options, chef_config) } before do allow(Chef::ServerAPI).to receive(:new).with(url, anything).and_return(http_client) end context "when using revision id" do let(:source_options) do { server: url, policy_name: policy_name, policy_revision_id: policy_revision_id, } end it "calls the chef server to get the policy" do expect(http_client).to receive(:get).with("policies/#{policy_name}/revisions/#{policy_revision_id}") .and_return(minimal_lockfile) expect(fetcher.lock_data).to eq(minimal_lockfile_modified) end context "and policy_name is not provided" do let(:source_options) do { server: url, policy_revision_id: policy_revision_id, } end it "calls the chef server to get the policy with the dsl name" do expect(http_client).to receive(:get).with("policies/#{policy_name}/revisions/#{policy_revision_id}") .and_return(minimal_lockfile) expect(fetcher.lock_data).to eq(minimal_lockfile_modified) end end end context "when using policy group" do let(:source_options) do { server: url, policy_name: policy_name, policy_group: policy_group, } end let(:source_options_for_lock) do source_options.merge({ policy_revision_id: revision_id }) end it "calls the chef server to get the policy" do expect(http_client).to receive(:get).with("policy_groups/#{policy_group}/policies/#{policy_name}") .and_return(minimal_lockfile) expect(fetcher.lock_data).to eq(minimal_lockfile_modified) end it "includes the revision id in the source_options_for_lock" do allow(http_client).to receive(:get).with( "policy_groups/#{policy_group}/policies/#{policy_name}" ).and_return(minimal_lockfile) expect(fetcher.source_options_for_lock).to eq(source_options_for_lock) end it "correctly applies source_options that were included in the lock" do fetcher.apply_locked_source_options(source_options_for_lock) expect(http_client).to receive(:get).with( "policies/#{policy_name}/revisions/#{revision_id}" ).and_return(minimal_lockfile) fetcher.lock_data end end end