【问题标题】:Chefspec with Hashicorp VaultChefspec 与 Hashicorp Vault
【发布时间】:2017-01-20 09:15:32
【问题描述】:

我正在尝试使用 ChefSpec 来测试 Chef 和 Hashicorp Vault 的实现

食谱

chef_gem 'vault' do
  compile_time true if Chef::Resource::ChefGem.instance_methods(false).include?(:compile_time)
end

require 'vault'

Vault.address = 'https://address:8200'
Vault.token = citadel['foo/bar']
Vault.auth_token.renew_self

测试

require_relative '../spec_helper'

describe 'wrapper::default' do
  context 'role is foo' do
    let(:chef_run) do
      ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |node|
        node.default['role'] = 'foo'
        const_set(:Vault, Module.new)
      end.converge(described_recipe)
    end

    before(:each) do
      allow_any_instance_of(Chef::Recipe).to receive(:require).and_call_original
      allow_any_instance_of(Chef::Recipe).to receive(:require).with('vault').and_return(true)
      allow_any_instance_of(::Vault).to receive(:address).and_call_original
      allow_any_instance_of(::Vault).to receive(:address).with('https://localhost:8200').and_return(true)
    end

    it 'install vault gem' do
      expect(chef_run).to install_chef_gem('vault')
    end
  end
end

错误

Failure/Error: expect(Chef::Recipe::Vault).to receive(:address).and_call_original

     NameError:
       uninitialized constant Vault

如何存根 Vault 变量?这是 Hashicorp Vault,而不是 chef-vault。

【问题讨论】:

  • 你解决了吗?你能分享你的解决方案吗?
  • 这就是我最终要做的:stackoverflow.com/a/59981857/303114

标签: chef-infra hashicorp-vault chefspec


【解决方案1】:

我到了这里还是想不通 所以我最终将我的库代码移动到我自己的库中,我将其包含在配方中,因此我无法在 ChefSpec 运行期间对其进行模拟。

所以我在my-cookbook/libraries/my_vault.rb 下使用此代码:

require 'vault'

module MyVault
  module Helpers
    def get_vault_secret(secret)
      Vault.configure do |config|
        config.address = "#{node[:vault_url]}"
        config.token = "#{node[:vault_token]}"
      end
      Vault.logical.read(secret)
    end
  end
end

在我的食谱中:

Chef::Recipe.send(:include, MyVault::Helpers)

creds = get_vault_secret("secret/jmx")
user = creds.data[:user]
password = creds.data[:password]


template "/etc/app/jmx.password" do
  source "jmx.password.erb"
  mode 0600
  owner "dev"
  group "dev"
  variables({
                :user => user,
                :password => password
            })
end


和我的规格测试:

require 'chefspec'
require 'chefspec/berkshelf'

describe 'app::metrics' do
  platform 'ubuntu', '14.04'

  before do
    response = Object.new
    allow(response).to receive_messages(:data => {
        :user => "benzi",
        :password => "benzi"
    })
    allow_any_instance_of(Chef::Recipe).to receive(:get_vault_secret).and_return(response)
  end


  describe 'adds jmx.access to app folder' do
    it { is_expected.to create_template('/etc/app/jmx.access')
        .with(
            user: 'dev',
            group: 'dev',
            mode: 0644
        ) }
  end

【讨论】:

    【解决方案2】:

    我已经回复了您的电子邮件,您需要 allow_any_instance_of(::Vault) 和类似的,如果模块 (const_set(:Vault, Module.new)) 尚不存在,您可能需要创建它。

    【讨论】:

    • 更新了我的问题,我添加了一个常量并取出了 Chef::Recipe,仍然得到未初始化的常量
    • 请查看上面的第二个位,您需要使用const_setstub_const 创建模块,然后才能在其上存根。
    • 你能分享一个完整的sn-p吗?我面临着让它发挥作用的真正挑战......
    • ChefSpec 自 2016 年以来发生了很大变化,因此这里的答案不再相关。大约 2 年前,我重写了加载器子系统,以使存根更自然。
    • 这就是我最终要做的:stackoverflow.com/a/59981857/303114
    猜你喜欢
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2017-05-16
    • 2019-07-28
    • 2017-12-18
    相关资源
    最近更新 更多