Skip to content

Commit

Permalink
Merge pull request #37 from da-ar/simple_get_filter
Browse files Browse the repository at this point in the history
(PDK-512) Add support for simple_get_filter
  • Loading branch information
DavidS authored Mar 20, 2018
2 parents 0dcab81 + ab2c3a7 commit 3d1d547
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 13 deletions.
30 changes: 21 additions & 9 deletions lib/puppet/resource_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def register_type(definition)
raise Puppet::DevError, 'requires attributes' unless definition.key? :attributes

definition[:features] ||= []
supported_features = %w[supports_noop canonicalize].freeze
supported_features = %w[supports_noop canonicalize remote_resource simple_get_filter].freeze
unknown_features = definition[:features] - supported_features
Puppet.warning("Unknown feature detected: #{unknown_features.inspect}") unless unknown_features.empty?

Expand All @@ -38,15 +38,23 @@ def my_provider
self.class.my_provider
end

if definition[:features] && definition[:features].include?('remote_resource')
define_singleton_method(:feature_support?) do |feature|
definition[:features] && definition[:features].include?(feature)
end

def feature_support?(feature)
self.class.feature_support?(feature)
end

if feature_support?('remote_resource')
apply_to_device
end

define_method(:initialize) do |attributes|
# $stderr.puts "A: #{attributes.inspect}"
attributes = attributes.to_hash if attributes.is_a? Puppet::Resource
# $stderr.puts "B: #{attributes.inspect}"
if definition.key?(:features) && definition[:features].include?('canonicalize')
if feature_support?('canonicalize')
attributes = my_provider.canonicalize(context, [attributes])[0]
end
# $stderr.puts "C: #{attributes.inspect}"
Expand Down Expand Up @@ -164,10 +172,15 @@ def my_provider

define_method(:retrieve) do
# puts "retrieve(#{title.inspect})"
result = Puppet::Resource.new(self.class, title)
current_state = my_provider.get(context).find { |h| h[namevar_name] == title }
result = Puppet::Resource.new(self.class, title)

current_state = if feature_support?('simple_get_filter')
my_provider.get(context, [title]).first
else
my_provider.get(context).find { |h| h[namevar_name] == title }
end

strict_check(current_state) if current_state && (definition.key?(:features) && definition[:features].include?('canonicalize'))
strict_check(current_state) if current_state && feature_support?('canonicalize')

# require 'pry'; binding.pry

Expand All @@ -187,11 +200,10 @@ def my_provider

define_method(:flush) do
# puts 'flush'
# require'pry';binding.pry
target_state = Hash[@parameters.map { |k, v| [k, v.value] }]
# remove puppet's injected metaparams
target_state.delete(:loglevel)
target_state = my_provider.canonicalize(context, [target_state]).first if definition.key?(:features) && definition[:features].include?('canonicalize')
target_state = my_provider.canonicalize(context, [target_state]).first if feature_support?('canonicalize')

retrieve unless @rapi_current_state

Expand All @@ -200,7 +212,7 @@ def my_provider

Puppet.debug("Target State: #{target_state.inspect}")

if definition[:features] && definition[:features].include?('supports_noop')
if feature_support?('supports_noop')
my_provider.set(context, { title => { is: @rapi_current_state, should: target_state } }, noop: noop?)
else
my_provider.set(context, title => { is: @rapi_current_state, should: target_state }) unless noop?
Expand Down
10 changes: 10 additions & 0 deletions lib/puppet/resource_api/base_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ def failed?
@failed
end

def feature_support?(feature)
supported = Puppet::Type.type(@typename).feature_support?(feature)
if supported
Puppet.debug("#{@typename} supports `#{feature}`")
else
Puppet.debug("#{@typename} does not support `#{feature}`")
end
supported
end

[:debug, :info, :notice, :warning, :err].each do |level|
define_method(level) do |*args|
if args.length == 1
Expand Down
7 changes: 6 additions & 1 deletion lib/puppet/resource_api/simple_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ module Puppet::ResourceApi
class SimpleProvider
def set(context, changes)
changes.each do |name, change|
is = change.key?(:is) ? change[:is] : (get(context) || []).find { |r| r[:name] == name }
is = if context.feature_support?('simple_get_filter')
change.key?(:is) ? change[:is] : (get(context, [name]) || []).find { |r| r[:name] == name }
else
change.key?(:is) ? change[:is] : (get(context) || []).find { |r| r[:name] == name }
end

should = change[:should]

is = { name: name, ensure: 'absent' } if is.nil?
Expand Down
39 changes: 39 additions & 0 deletions spec/acceptance/simple_get_filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'spec_helper'

require 'open3'
require 'tempfile'

RSpec.describe 'exercising simple_get_filter' do
let(:common_args) { '--verbose --debug --trace --modulepath spec/fixtures' }

describe 'using `puppet resource`' do
context 'when using `get` to access all resources' do
it 'does not receive names array' do
stdout_str, status = Open3.capture2e("puppet resource #{common_args} test_simple_get_filter")

expect(stdout_str.strip).to match %r{^test_simple_get_filter \{ \"bar\"}
expect(stdout_str.strip).to match %r{^test_simple_get_filter \{ \"foo\"}
expect(status).to eq 0
end
end

context 'when using `get` to access a specific resource' do
it 'does not receive names array' do
stdout_str, status = Open3.capture2e("puppet resource #{common_args} test_simple_get_filter foo")

expect(stdout_str.strip).to match %r{test_string\s*=>\s*'default'}
expect(status).to eq 0
end
end

context 'when using `get` to access a specific resource' do
it 'receives names array' do
stdout_str, status = Open3.capture2e("puppet resource #{common_args} test_simple_get_filter foo ensure=absent")

expect(stdout_str.strip).to match %r{ensure\s*=>\s*'absent'}
expect(stdout_str.strip).to match %r{test_string\s*=>\s*'foo found'}
expect(status).to eq 0
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'puppet/resource_api'
require 'puppet/resource_api/simple_provider'

# Implementation for the test_simple_get_filter type using the Resource API.
class Puppet::Provider::TestSimpleGetFilter::TestSimpleGetFilter < Puppet::ResourceApi::SimpleProvider
def get(_context, names = nil)
if names.nil?
[
{
name: 'bar',
ensure: :present,
test_string: 'default'
},
{
name: 'foo',
ensure: :present,
test_string: 'default'
},
]
elsif names.include?('foo')
[
{
name: 'foo',
ensure: :absent,
test_string: 'foo found'
}
]
else
[
{
name: 'foo',
ensure: :present,
test_string: 'not foo'
}
]
end
end

def create(_context, _name, _should)
end

def update(_context, _name, _should)
end

def delete(_context, _name)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'puppet/resource_api'

Puppet::ResourceApi.register_type(
name: 'test_simple_get_filter',
docs: <<-EOS,
This type provides Puppet with the capabilities to manage ...
EOS
features: ['simple_get_filter'],
attributes: {
ensure: {
type: 'Enum[present, absent]',
desc: 'Whether this resource should be present or absent on the target system.',
default: 'present',
},
name: {
type: 'String',
desc: 'The name of the resource you want to manage.',
behaviour: :namevar,
},
test_string: {
type: 'String',
desc: 'Used for testing our expected outcomes',
},
},
)
21 changes: 21 additions & 0 deletions spec/puppet/resource_api/base_context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,25 @@ def send_log(log, msg)
describe '#send_log' do
it { expect { described_class.new(nil).send_log(nil, nil) }.to raise_error RuntimeError, %r{Received send_log\(\) on an unprepared BaseContext\. Use IOContext, or PuppetContext instead} }
end

describe '#feature_support?' do
let(:puppet_type) { double('A Resource API Type') } # rubocop:disable RSpec/VerifiedDoubles

before(:each) do
allow(Puppet::Type).to receive(:type).and_return(puppet_type)
allow(puppet_type).to receive(:feature_support?).with('simple_get_filter').and_return(return_val)
end

context 'when type supports feature' do
let(:return_val) { true }

it { expect(described_class.new('supported_feature')).to be_feature_support('simple_get_filter') }
end

context 'when type does not support a feature' do
let(:return_val) { false }

it { expect(described_class.new('supported_feature')).not_to be_feature_support('simple_get_filter') }
end
end
end
17 changes: 16 additions & 1 deletion spec/puppet/resource_api/simple_provider_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
let(:context) { instance_double('Puppet::ResourceApi::BaseContext', 'context') }
let(:provider_class) do
Class.new(described_class) do
def get(context); end
def get(context, _names = nil); end

def create(context, _name, _should); end

Expand Down Expand Up @@ -57,6 +57,7 @@ def delete(context, _name); end

before(:each) do
allow(context).to receive(:creating).with('title').and_yield
allow(context).to receive(:feature_support?).with('simple_get_filter')
end

it 'calls create once' do
Expand All @@ -71,6 +72,17 @@ def delete(context, _name); end
expect(provider).to receive(:delete).never
provider.set(context, changes)
end

context 'with a type that supports `simple_get_filter`' do
before(:each) do
allow(context).to receive(:feature_support?).with('simple_get_filter').and_return(true)
end

it 'calls `get` with name' do
expect(provider).to receive(:get).with(context, ['title'])
provider.set(context, changes)
end
end
end

context 'with a single change to update a resource' do
Expand All @@ -86,6 +98,7 @@ def delete(context, _name); end

before(:each) do
allow(context).to receive(:updating).with('title').and_yield
allow(context).to receive(:feature_support?).with('simple_get_filter')
end

it 'does not call create' do
Expand Down Expand Up @@ -115,6 +128,7 @@ def delete(context, _name); end

before(:each) do
allow(context).to receive(:deleting).with('title').and_yield
allow(context).to receive(:feature_support?).with('simple_get_filter')
end

it 'does not call create' do
Expand Down Expand Up @@ -153,6 +167,7 @@ def delete(context, _name); end
allow(context).to receive(:creating).with('to create').and_yield
allow(context).to receive(:updating).with('to update').and_yield
allow(context).to receive(:deleting).with('to delete').and_yield
allow(context).to receive(:feature_support?).with('simple_get_filter').exactly(3).times
end

it 'calls the crud methods' do
Expand Down
Loading

0 comments on commit 3d1d547

Please sign in to comment.