class ChefVault::TestFixtures

dynamic RSpec contexts for cookbooks that use chef-vault

dynamic RSpec contexts for cookbooks that use chef-vault

Constants

VERSION

the version of the gem

Public Class Methods

find_vaults(stub_encrypted_data) click to toggle source

finds all the directories in test/integration/data_bags, stubbing each as a vault @param stub_encrypted_data [Boolean] whether to also stub calls to

Chef::DataBagItem.load

return [void] @api private

# File lib/chef-vault/test_fixtures.rb, line 42
def find_vaults(stub_encrypted_data)
  dbdir = Pathname.new("test") + "integration" + "data_bags"
  smokedir = Pathname.new("test") + "smoke" + "default" + "data_bags"
  [ dbdir, smokedir ].each do |dir|
    next unless dir.directory?

    dir.each_child do |vault|
      next unless vault.directory?

      stub_vault(stub_encrypted_data, vault)
    end
  end
end
make_fakevault(vault, item) click to toggle source

returns an RSpec double that acts like a vault item @param vault [String] the name of the vault data bag @param item [String] the name of the vault item @return [RSpec::Mocks::Double] the vault double @api private

# File lib/chef-vault/test_fixtures.rb, line 159
def make_fakevault(vault, item)
  fakevault = double "vault item #{vault}/#{item}"
  allow(fakevault).to receive(:[]=).with(String, Object)
  allow(fakevault).to receive(:clients).with(String)
  allow(fakevault).to receive(:save)
  fakevault
end
rspec_shared_context(stub_encrypted_data = false) click to toggle source

created a shared RSpec context that stubs calls to ChefVault::Item.load @param stub_encrypted_data [Boolean] whether to also stub calls to

Chef::DataBagItem.load

@return [Module] a shared context to include in your example groups

# File lib/chef-vault/test_fixtures.rb, line 27
def rspec_shared_context(stub_encrypted_data = false)
  @context ||= begin
    Module.new do
      extend RSpec::Core::SharedContext

      before { find_vaults(stub_encrypted_data) }

      private

      # finds all the directories in test/integration/data_bags, stubbing
      # each as a vault
      # @param stub_encrypted_data [Boolean] whether to also stub calls to
      #   Chef::DataBagItem.load
      # return [void]
      # @api private
      def find_vaults(stub_encrypted_data)
        dbdir = Pathname.new("test") + "integration" + "data_bags"
        smokedir = Pathname.new("test") + "smoke" + "default" + "data_bags"
        [ dbdir, smokedir ].each do |dir|
          next unless dir.directory?

          dir.each_child do |vault|
            next unless vault.directory?

            stub_vault(stub_encrypted_data, vault)
          end
        end
      end

      # stubs a vault with the contents of JSON files in a directory.
      # Finds all files in the vault path ending in .json and stubs
      # each as a vault item.
      # @param stub_encrypted_data [Boolean] whether to also stub calls to
      #   Chef::DataBagItem.load
      # @param vault [Pathname] the path to the directory that will be
      #   stubbed as a vault
      # @return [void]
      # @api private
      def stub_vault(stub_encrypted_data, vault)
        db = {}
        vault.each_child do |e|
          next unless e.file?

          m = e.basename.to_s.downcase.match(/(.+)\.json/i)
          next unless m

          content = JSON.parse(e.read)
          vaultname = vault.basename.to_s
          stub_vault_item(vaultname, m[1], content, db)
          if stub_encrypted_data
            stub_vault_item_encrypted_data(vaultname, m[1], content)
          end
        end
      end

      # stubs a vault item with the contents of a parsed JSON string.
      # If the class-level setting `encrypted_data_stub` is true, then
      # Chef::DataBagItem.load
      # @param vault [String] the name of the vault data bag
      # @param item [String] the name of the vault item
      # @param content [String] the JSON-encoded contents to populate the
      #   fake vault with
      # @param db [Hash] the fake data bag item that contains the item
      # @return [void]
      # @api private
      def stub_vault_item(vault, item, content, db)
        db["#{item}_keys"] = true
        vi = make_fakevault(vault, item)

        # stub vault lookup of each of the vault item keys
        content.each do |k, v|
          next if "id" == k

          allow(vi).to receive(:[]).with(k).and_return(v)
        end

        # stub hash conversion as a stopgap to other hash methods
        allow(vi).to receive(:to_h).with(no_args).and_return(content)
        allow(vi).to receive(:to_hash).with(no_args).and_return(content)

        # stub ChefVault and Chef::DataBag to return the doubles
        # via both symbol and string forms of the data bag name
        [vault, vault.to_sym].each do |dbname|
          allow(ChefVault::Item).to(
            receive(:vault?).with(dbname, item).and_return(true)
          )

          allow(ChefVault::Item).to(
            receive(:load)
            .with(dbname, item)
            .and_return(vi)
          )
          allow(Chef::DataBag).to(
            receive(:load)
            .with(dbname)
            .and_return(db)
          )
        end
      end

      # stubs Chef::DataBagItem.load to return a fake hash in which
      # each key of the content returns a hash with single
      # `encrypted_data` key, which fools some attempts to determine
      # whether a data bag is a vault
      # @param vault [String] the name of the vault data bag
      # @param item [String] the name of the vault item
      # @param content [String] the JSON-encoded contents to populate the
      #   fake vault with
      # @return [void]
      # @api private
      def stub_vault_item_encrypted_data(vault, item, content)
        # stub data bag lookup of each of the vault item keys
        dbi = ChefVault::TestFixtureDataBagItem.new
        dbi["raw_data"] = content
        content.each_key do |k|
          next if "id" == k

          dbi[k] = { "encrypted_data" => "..." }
        end

        [vault, vault.to_sym].each do |dbname|
          allow(Chef::DataBagItem).to(
            receive(:load).with(dbname, item).and_return(dbi)
          )
        end
      end

      # returns an RSpec double that acts like a vault item
      # @param vault [String] the name of the vault data bag
      # @param item [String] the name of the vault item
      # @return [RSpec::Mocks::Double] the vault double
      # @api private
      def make_fakevault(vault, item)
        fakevault = double "vault item #{vault}/#{item}"
        allow(fakevault).to receive(:[]=).with(String, Object)
        allow(fakevault).to receive(:clients).with(String)
        allow(fakevault).to receive(:save)
        fakevault
      end
    end
  end
end
stub_vault(stub_encrypted_data, vault) click to toggle source

stubs a vault with the contents of JSON files in a directory. Finds all files in the vault path ending in .json and stubs each as a vault item. @param stub_encrypted_data [Boolean] whether to also stub calls to

Chef::DataBagItem.load

@param vault [Pathname] the path to the directory that will be

stubbed as a vault

@return [void] @api private

# File lib/chef-vault/test_fixtures.rb, line 65
def stub_vault(stub_encrypted_data, vault)
  db = {}
  vault.each_child do |e|
    next unless e.file?

    m = e.basename.to_s.downcase.match(/(.+)\.json/i)
    next unless m

    content = JSON.parse(e.read)
    vaultname = vault.basename.to_s
    stub_vault_item(vaultname, m[1], content, db)
    if stub_encrypted_data
      stub_vault_item_encrypted_data(vaultname, m[1], content)
    end
  end
end
stub_vault_item(vault, item, content, db) click to toggle source

stubs a vault item with the contents of a parsed JSON string. If the class-level setting `encrypted_data_stub` is true, then Chef::DataBagItem.load @param vault [String] the name of the vault data bag @param item [String] the name of the vault item @param content [String] the JSON-encoded contents to populate the

fake vault with

@param db [Hash] the fake data bag item that contains the item @return [void] @api private

# File lib/chef-vault/test_fixtures.rb, line 92
def stub_vault_item(vault, item, content, db)
  db["#{item}_keys"] = true
  vi = make_fakevault(vault, item)

  # stub vault lookup of each of the vault item keys
  content.each do |k, v|
    next if "id" == k

    allow(vi).to receive(:[]).with(k).and_return(v)
  end

  # stub hash conversion as a stopgap to other hash methods
  allow(vi).to receive(:to_h).with(no_args).and_return(content)
  allow(vi).to receive(:to_hash).with(no_args).and_return(content)

  # stub ChefVault and Chef::DataBag to return the doubles
  # via both symbol and string forms of the data bag name
  [vault, vault.to_sym].each do |dbname|
    allow(ChefVault::Item).to(
      receive(:vault?).with(dbname, item).and_return(true)
    )

    allow(ChefVault::Item).to(
      receive(:load)
      .with(dbname, item)
      .and_return(vi)
    )
    allow(Chef::DataBag).to(
      receive(:load)
      .with(dbname)
      .and_return(db)
    )
  end
end
stub_vault_item_encrypted_data(vault, item, content) click to toggle source

stubs Chef::DataBagItem.load to return a fake hash in which each key of the content returns a hash with single `encrypted_data` key, which fools some attempts to determine whether a data bag is a vault @param vault [String] the name of the vault data bag @param item [String] the name of the vault item @param content [String] the JSON-encoded contents to populate the

fake vault with

@return [void] @api private

# File lib/chef-vault/test_fixtures.rb, line 137
def stub_vault_item_encrypted_data(vault, item, content)
  # stub data bag lookup of each of the vault item keys
  dbi = ChefVault::TestFixtureDataBagItem.new
  dbi["raw_data"] = content
  content.each_key do |k|
    next if "id" == k

    dbi[k] = { "encrypted_data" => "..." }
  end

  [vault, vault.to_sym].each do |dbname|
    allow(Chef::DataBagItem).to(
      receive(:load).with(dbname, item).and_return(dbi)
    )
  end
end