Added support for Notify/Subscribe

Since eval_generate executed after relationship_graph has been formed we
need to insert dependencies for new resources

Change-Id: Ic9ad10cc4eb5ddbcd9ecf673b0bff3728b1d51e3
Closes-Bug: 1649380
Closes-Bug: 1644656
This commit is contained in:
Dmitry Ukov 2016-12-12 23:15:48 +04:00
parent 5035ca27e1
commit 0e29cd247d
2 changed files with 89 additions and 18 deletions

View File

@ -249,6 +249,7 @@ Puppet::Type.newtype(:override_resources) do
# @param [String] type
# @param [String] title
# @param [Hash<String>] parameters
# @return [Puppet::Type]
def update_resource(type, title, parameters = {})
resource = catalog.resource type, title
unless resource
@ -256,9 +257,14 @@ Puppet::Type.newtype(:override_resources) do
return false
end
parameters.each do |parameter, value|
resource[parameter] = value
if [:notify, :require, :before, :subscribe].include? parameter.to_sym
current_values = resource[parameter] || []
resource[parameter] = current_values << value
else
resource[parameter] = value
end
end
true
resource
end
# Check if a resource with the given type and title
@ -278,7 +284,33 @@ Puppet::Type.newtype(:override_resources) do
# @return [Puppet::Type]
def create_resource(type, title, parameters = {})
parameters = parameters.merge(:name => title)
Puppet::Type.type(type.to_sym).new(parameters)
resource = Puppet::Type.type(type.to_sym).new(parameters)
catalog.add_resource(resource)
resource
end
# Update relationship graph for new or updated resources.
# This is needed to handle notifications for resources that
# were created or updated during eval_generate since
# relationship graph finalised at this moment
# @param [Array<Puppet::Type>]
def update_relationship_graph(resources)
rel_graph = catalog.relationship_graph
inserted_edges = []
resources.map {|res| res.builddepends}.flatten.each do |dep|
unless !!rel_graph.edge?(dep.source, dep.target)
rel_graph.add_edge dep
inserted_edges << dep
end
end
begin
rel_graph.report_cycles_in_graph
rescue Puppet::Error => err
debug 'There are cycles in graph (see error below). Need to remove recently added edges'
inserted_edges.each {|edge| rel_graph.remove_edge! edge }
raise
end
end
# The main method of this metatype. Updates the existing resources
@ -288,6 +320,8 @@ Puppet::Type.newtype(:override_resources) do
# @return [Array<Puppet::Type>]
def eval_generate
new_resources = []
updated_resources = []
configuration.each do |type, resources|
fail "The 'type' should be the name of the Puppet type and not be empty! Got: #{type.inspect}" unless type and not type.empty?
fail "The 'resources' should be a hash with the override Puppet resources! Got: #{resources.inspect}" unless resources.is_a? Hash
@ -302,7 +336,7 @@ Puppet::Type.newtype(:override_resources) do
if resource_present? type, title
debug "#{type.capitalize}[#{title}] was found in the catalog, updating it!"
update_resource type, title, parameters
updated_resources << update_resource(type, title, parameters)
else
if type_create? type or title_create? title
debug "#{type.capitalize}[#{title}] was not found in the catalog, creating it!"
@ -315,6 +349,8 @@ Puppet::Type.newtype(:override_resources) do
end
end
update_relationship_graph(updated_resources + new_resources)
new_resources
end

View File

@ -4,6 +4,17 @@ require 'yaml'
describe Puppet::Type.type(:override_resources) do
let(:facts) do
{
:osfamily => 'Debian',
:operatingsystem => 'Debian',
}
end
let(:catalog) do
Puppet::Resource::Catalog.new()
end
let(:override_resources) do
Puppet::Type.type(:override_resources).new(
:name => 'foo',
@ -17,23 +28,14 @@ describe Puppet::Type.type(:override_resources) do
let(:configuration) do
YAML.load <<-eof
---
nova_config:
DEFAULT/debug:
value: true
DEFAULT/verbose:
ensure: absent
file:
'/tmp/test':
content: 123
content: "123"
'/etc/httpd/httpd.conf':
source: 'puppet:///modules/httpd/httpd.conf'
owner: httpd
group: httpd
notify: 'Service[httpd]'
my_symlink:
ensure: symlink
path: '/tmp/test1'
target: '/tmp/test'
service:
httpd:
ensure: running
@ -42,13 +44,10 @@ service:
ensure: stopped
enable: false
package:
mc:
htop:
ensure: absent
ntpd:
ensure: latest
my_package:
ensure: 1
ensure: present
eof
end
@ -68,6 +67,17 @@ defaults:
eof
end
let(:conf_with_cycle) do
YAML.load <<-eof
---
file:
'/tmp/foo':
notify: "File[/tmp/bar]"
'/tmp/bar':
notify: "File[/tmp/foo]"
eof
end
it 'should require a name' do
expect {
Puppet::Type.type(:override_resources).new({})
@ -126,4 +136,29 @@ defaults:
override_resources[:create] = cr
expect(override_resources[:create]).to eq(cr)
end
it 'should create resource with notify' do
catalog.clear
override_resources.catalog = catalog
override_resources[:create] = true
override_resources.eval_generate
opts = {'event' => :ALL_EVENTS, 'callback' => :refresh}
source_resource = catalog.resource 'file', '/etc/httpd/httpd.conf'
target_resource = catalog.resource 'service', 'httpd'
relationship = Puppet::Relationship.new(source_resource, target_resource, options=opts)
expect(
catalog.relationship_graph.edges.map {|e| e.to_json}.include? relationship.to_json
).to eq(true)
end
it 'should raise for config with cycles' do
catalog.clear
override_resources.catalog = catalog
override_resources[:create] = true
override_resources[:configuration] = conf_with_cycle
expect {
override_resources.eval_generate
}.to raise_error(Puppet::Error, /dependency cycle/)
end
end