-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move bulk of logic to PuppetX::VaultLookup::Lookup #77
Conversation
bef30ba
to
724836e
Compare
Yes
Agree, that would be awesome.
We added a setting in puppet 7 so it's possible to evaluate deferred functions lazily when the resource is evaluated. And that is the default behavior in puppet 8 (see https://tickets.puppetlabs.com/browse/PUP-9323) My expectation is if you set
I'm not sure I understand this part. I would expect rspec-puppet to be able to stub Puppet-language functions, even those that are deferred. It may be that rspec-puppet hasn't pushed the loaders onto the context so or something like that? |
724836e
to
bf0a574
Compare
@joshcooper from slack conversation, when stubbing a Puppet language function that ends up being deferred, this exception is raised:
Are you suggesting that something like this might make those function deferrable in this context? rodjek/rspec-puppet#825 |
@joshcooper That sounds ideal, but I'm not sure I understand specifically what you mean. Do you have an example? Also, wouldn't we still want to allow this function's evaluation to be stubbed for cases where eager evaluation is used, and to make spec testing scenarios easier? Stubbing as a puppet-language function
The only way that I'm aware of to stub a Ruby-API function in an rspec-puppet test is by defining a Puppet-language function of the same name. For example, given this Puppet code that does NOT use deferred: file { '/etc/creds.txt':
ensure => file,
content => vault_lookup::lookup($path, $opts),
} ✅ This rspec-puppet test works, and the stub function is used instead of the real function: # In an rspec-puppet test for a class or defined type
# NOTE: This stub works only when vault_lookup::lookup() is NOT deferred.
let(:pre_condition) do
'function vault_lookup::lookup($path, $opts) { Sensitive("hello world") }'
end
it { is_expected.to compile }
it { is_expected.to contain_file('/etc/creds.txt').with_content(sensitive('hello world')) } But when the Puppet code is updated to use file { '/etc/creds.txt':
ensure => file,
content => Deferred('vault_lookup::lookup', [$path, $opts]),
} ❌ The rspec-puppet test fails with:
Stubbing as a ruby-api functionIf I try to redefine the function as a Ruby-API function, the real function is used instead (though I admit I'm not convinced that this would be expected to work at all). So given this deferred function call in Puppet: file { '/etc/creds.txt':
ensure => file,
content => Deferred('vault_lookup::lookup', [$path, $opts]),
} And this rspec-puppet test: # This does NOT work. The real function is called instead of this one.
before(:each) do
Puppet::Functions.create_function(:'vault_lookup::lookup') do
def lookup(path,opts)
Puppet::Pops::Types::PSensitiveType::Sensitive.new('hello world')
end
end
end
it { is_expected.to compile } ❌ The rspec-puppet tests fail with errors related to the fact that the real function is being evaluated. In this case, it bombs out on the token file not existing locally when attempting to use
|
bf0a574
to
5330603
Compare
@joshcooper (or anyone else) One quirk with this change is that spec tests for Puppet code need to add the following require_relative '../fixtures/modules/vault_lookup/lib/puppet_x/vault_lookup/lookup'
# ...snip...
before(:each) do
allow(PuppetX::VaultLookup::Lookup).to receive(:lookup)
.and_return(Puppet::Pops::Types::PSensitiveType::Sensitive.new('hello world'))
end Is that expected? It feels wrong to be to have to Without that line, the spec tests fail with: NameError:
uninitialized constant PuppetX |
5330603
to
2a1f5fa
Compare
2a1f5fa
to
f210420
Compare
f210420
to
35c60ff
Compare
Thanks @bastelfreak I'll merge this when those tests are complete and I'm confident in this change. |
Problem
The
vault_lookup::lookup()
function can not be stubbed/mocked in an rspec-puppet test when the function is deferred withDeferred()
.For example, say you're writing a spec test for a defined type that calls
vault_lookup::lookup()
withDeferred
. If you run your tests, you'll see that:e.g.
The problem is that the vault_lookup::lookup() function isn't actually being deferred in rspec-puppet. It's being evaluated because of this change: rodjek/rspec-puppet#740
Also, stubbing the function as a Puppet-language function doesn't work either. For example:
You'll see that rspec fails with:
Solution
Move all of
vault_lookup::lookup()
's code into aPuppetX
namespaced module so that there's a Ruby class whose methods can be stubbed using regularallow(<class>).to receive(<method>).and_return(<value>)
patterns.In this case, the internals of the function are moving to:
Outcome
The
vault_lookup::lookup()
function retains the exact same behavior as before when used in Puppet code.The function's evaluation and return value and be stubbed in an rspec-puppet test like this: