spec/chef-vault/item_spec.rb in chef-vault-2.4.0 vs spec/chef-vault/item_spec.rb in chef-vault-2.5.0
- old
+ new
@@ -1,10 +1,61 @@
+require 'openssl'
+require 'rspec/core/shared_context'
+
+# it turns out that simulating a node that doesn't have a public
+# key is not a simple thing
+module BorkedNodeWithoutPublicKey
+ extend RSpec::Core::SharedContext
+
+ before do
+ # a node 'foo' with a public key
+ node_foo = double('chef node foo')
+ allow(node_foo).to receive(:name).and_return('foo')
+ client_foo = double('chef apiclient foo')
+ allow(client_foo).to receive(:name).and_return('foo')
+ privkey = OpenSSL::PKey::RSA.new(1024)
+ pubkey = privkey.public_key
+ allow(client_foo).to receive(:public_key).and_return(pubkey.to_pem)
+ # a node 'bar' without a public key
+ node_bar = double('chef node bar')
+ allow(node_bar).to receive(:name).and_return('bar')
+ # fake out searches to return both of our nodes
+ query_result = double('chef search results')
+ allow(query_result)
+ .to receive(:search)
+ .with(Symbol, String)
+ .and_return([[node_foo, node_bar]])
+ allow(Chef::Search::Query)
+ .to receive(:new)
+ .and_return(query_result)
+ # create a new vault item
+ @vaultitem = ChefVault::Item.new('foo', 'bar')
+ @vaultitem['foo'] = 'bar'
+ # make the vault item return the apiclient for foo but raise for bar
+ allow(@vaultitem).to receive(:load_client).with('foo')
+ .and_return(client_foo)
+ allow(@vaultitem).to receive(:load_client).with('bar')
+ .and_raise(ChefVault::Exceptions::ClientNotFound)
+ # make the vault item fall back to 'load-admin-as-client' behaviour
+ http_response = double('http not found')
+ allow(http_response).to receive(:code).and_return('404')
+ http_not_found = Net::HTTPServerException.new('not found', http_response)
+ allow(ChefVault::ChefPatch::User)
+ .to receive(:load)
+ .with('foo')
+ .and_return(client_foo)
+ allow(ChefVault::ChefPatch::User)
+ .to receive(:load)
+ .with('bar')
+ .and_raise(http_not_found)
+ end
+end
+
RSpec.describe ChefVault::Item do
subject(:item) { ChefVault::Item.new("foo", "bar") }
describe '#new' do
-
it { should be_an_instance_of ChefVault::Item }
its(:keys) { should be_an_instance_of ChefVault::ItemKeys }
its(:data_bag) { should eq "foo" }
@@ -19,8 +70,33 @@
describe '#save' do
context 'when item["id"] is bar.bar' do
let(:item) { ChefVault::Item.new("foo", "bar.bar") }
specify { expect { item.save }.to raise_error }
+ end
+ end
+
+ describe '#clients' do
+ include BorkedNodeWithoutPublicKey
+
+ it 'should not blow up when search returns a node without a public key' do
+ # try to set clients when we know a node is missing a public key
+ # this should not die as of v2.4.1
+ expect { @vaultitem.clients('*:*') }.not_to raise_error
+ end
+
+ it 'should emit a warning if search returns a node without a public key' do
+ # it should however emit a warning that you have a borked node
+ expect { @vaultitem.clients('*:*') }
+ .to output(/node 'bar' has no private key; skipping/).to_stderr
+ end
+ end
+
+ describe '#admins' do
+ include BorkedNodeWithoutPublicKey
+
+ it 'should blow up if you try to use a node without a public key as an admin' do
+ expect { @vaultitem.admins('foo,bar') }
+ .to raise_error(ChefVault::Exceptions::AdminNotFound)
end
end
end