cookbooks/fb_chef_hints/spec/default_spec.rb (265 lines of code) (raw):

# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2 # # Copyright (c) 2020-present, Facebook, Inc. # All rights reserved. # # 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_relative '../libraries/chef_hints_helpers.rb' require_relative '../../fb_helpers/libraries/fb_helpers.rb' require 'chef/node' describe FB::ChefHints do context 'valid_hints?' do it 'returns false if source is missing' do hint = { 'hint' => { 'foo' => 1, }, } expect(FB::ChefHints.valid_hints?(hint)).to eq(false) end it 'returns false if hint is missing' do expect(FB::ChefHints.valid_hints?({ 'source' => 'foo' })). to eq(false) end it 'returns false if source is not allowed' do hint = { 'source' => 'foo', 'hint' => { 'foo' => 1, }, } expect(FB::ChefHints.valid_hints?(hint)).to eq(false) end it 'returns true if source is allowed' do hint = { 'source' => 'foo', 'hint' => { 'foo' => 1, }, } expect(FB::ChefHints.valid_hints?(hint, ['foo'])). to eq(true) end end context 'apply_hints' do it 'skips a hint if source is not allowed' do FB::ChefHintsSiteData::ALLOWED_SOURCES = [].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => 0, }, }, } node = Chef::Node.new node.default['foo']['bar'] = 1 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(1) end it 'skips a hint if hint is not allowed' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = [].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => 0, }, }, } node = Chef::Node.new node.default['foo']['bar'] = 1 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(1) end it 'sets an allowed leaf Integer attribute hint' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => 0, }, }, } node = Chef::Node.new node.default['foo']['bar'] = 1 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(0) end it 'sets an allowed leaf String attribute hint' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => 'pie', }, }, } node = Chef::Node.new node.default['foo']['bar'] = 'cake' allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq('pie') end it 'sets an allowed leaf Array attribute hint' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => ['pie'], }, }, } node = Chef::Node.new node.default['foo']['bar'] = ['cake'] allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(['pie']) end it 'sets an allowed leaf Hash attribute hint' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => { 'pie' => 1 }, }, }, } node = Chef::Node.new node.default['foo']['bar'] = { 'cake' => 1 } allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq({ 'pie' => 1 }) end it 'clears an allowed leaf Array attribute hint' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => [], }, }, } node = Chef::Node.new node.default['foo']['bar'] = ['cake'] allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq([]) end it 'clears an allowed leaf Hash attribute hint' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => {}, }, }, } node = Chef::Node.new node.default['foo']['bar'] = { 'cake' => 1 } allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq({}) end it 'leaves attributes unchanged if filter does not match' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo/bar/cake'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => { 'pie' => { 'baz' => 1, }, }, }, }, } node = Chef::Node.new node.default['foo']['bar']['pie']['baz'] = 1 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']['pie']['baz']).to eq(1) end it 'does not clobber other attributes in the hash when setting a int' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo/bar'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => 1, }, }, } node = Chef::Node.new node.default['foo']['cake'] = 2 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(hint['hint']['foo']['bar']) expect(node['foo']['cake']).to eq(2) end it 'does not clobber other attributes in the hash when setting an array' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo/bar'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => [1, 2, 3], }, }, } node = Chef::Node.new node.default['foo']['cake'] = 2 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(hint['hint']['foo']['bar']) expect(node['foo']['cake']).to eq(2) end it 'does not clobber other attributes in the hash when setting a hash' do FB::ChefHintsSiteData::ALLOWED_SOURCES = ['chefspec'].freeze FB::ChefHintsSiteData::ALLOWED_HINTS = ['foo/bar'].freeze hint = { 'source' => 'chefspec', 'hint' => { 'foo' => { 'bar' => { 'baz' => 1, }, }, }, } node = Chef::Node.new node.default['foo']['cake'] = 2 allow(FB::Helpers).to receive(:parse_json_file). with('hint.json', Hash, true).and_return(hint) FB::ChefHints.apply_hint(node, 'hint.json') expect(node['foo']['bar']).to eq(hint['hint']['foo']['bar']) expect(node['foo']['cake']).to eq(2) end end end