Update merge_yaml implementation

Switch to the upstream merge_yaml_settings version.

Change-Id: Ie78868937a90e0c1af24221ca43849c0c4b9cdbf
This commit is contained in:
Dmitry Ilyin
2016-09-16 12:39:08 -05:00
parent f7a5a8b81f
commit 31553addf7
11 changed files with 290 additions and 72 deletions

View File

@@ -0,0 +1,2 @@
spec/fixtures
Gemfile.lock

View File

@@ -0,0 +1,2 @@
gem 'puppetlabs_spec_helper'
gem 'puppet'

View File

@@ -0,0 +1 @@
require 'puppetlabs_spec_helper/rake_tasks'

View File

@@ -0,0 +1,124 @@
require 'yaml'
Puppet::Type.type(:ceilometer_pipeline_section).provide(:ruby) do
attr_accessor :resource
# Alias to the yaml file path
# @return [String]
def yaml_file_path
resource[:path]
end
# Alias to the array name
# @return [String]
def array_name
resource[:array_name]
end
# Alias to the section name
# @return [String]
def section_name
resource[:section_name]
end
# The exiting data read from the YAML file
# @return [Hash]
def existing_data
return @yaml_file_existing_data if @yaml_file_existing_data
begin
@yaml_file_existing_data = YAML.load_file resource[:path]
fail "YAML data should be a hash in the file: '#{yaml_file_path}'!" unless @yaml_file_existing_data.is_a? Hash
@yaml_file_existing_data
rescue => exception
warn "Could not read the YAML file: '#{yaml_file_path}' #{exception}"
@yaml_file_existing_data = {}
end
end
# Write the expected data to the YAML file
def yaml_file_write
File.open(yaml_file_path, 'w') do |file|
file.puts YAML.dump expected_data
end
end
# The expected YAML data with updated hardware_source section
# @return [Hash]
def expected_data
return @yaml_file_expected_data if @yaml_file_expected_data
@yaml_file_expected_data = Marshal.load Marshal.dump existing_data
@yaml_file_expected_data[array_name] = [] unless @yaml_file_expected_data[array_name]
if resource[:ensure] == :present
modify_section @yaml_file_expected_data
else
remove_section @yaml_file_expected_data
end
@yaml_file_expected_data
end
# Update the selected section in the
# provided YAML data or add a new section if
# it's missing.
# @param [Hash] data
def modify_section(data)
sources = data.fetch array_name, []
target_section = section data
if target_section
target_section.clear
target_section.merge! resource[:data]
target_section['name'] = section_name
else
sources << new_section
end
sources
end
# Extract rhe hardware_source section from the data
# @param [Hash] data
# @return [Hash]
def section(data)
sources = data.fetch array_name, []
sources.find do |source|
next unless source.is_a? Hash
source['name'] == section_name
end
end
# Remove the hardware_source section from the data
# @param [Hash] data
def remove_section(data)
sources = data.fetch array_name, []
sources.reject! do |source|
source['name'] == section_name
end
sources
end
# Generate a new hardware_source section
# @return [Hash]
def new_section
section = resource[:data]
section['name'] = section_name
section
end
#####
def exists?
if resource[:ensure] == :absent
!section(existing_data).nil?
else
existing_data == expected_data
end
end
def create
yaml_file_write
end
def destroy
yaml_file_write
end
end

View File

@@ -1,42 +0,0 @@
require 'yaml'
require 'deep_merge'
Puppet::Type.type(:merge_yaml_settings).provide(:ruby) do
desc "Support for merging yaml configuration files."
def create
merged_settings = get_merged_settings
write_to_file(@resource[:path], merged_settings.to_yaml.gsub( "x5c", "\\" )) if not (merged_settings.empty?)
end
def destroy
File.unlink(@resource[:path])
end
def exists?
get_dict(@resource[:sample_settings]) == get_merged_settings
end
def get_merged_settings
sample_settings = get_dict(@resource[:sample_settings])
override_settings = get_dict(@resource[:override_settings])
sample_settings.deep_merge(override_settings)
end
def write_to_file(filename, content)
debug "writing content #{content} to the file #{filename}"
begin
File.open(filename, "w") { |f| f.puts content }
rescue
raise Puppet::Error, "merge_yaml_settings: the file #{filename} can not be written!"
end
end
def get_dict(obj)
return obj if obj.is_a?(Hash)
YAML.load_file(obj) rescue {}
end
private :get_merged_settings, :get_dict, :write_to_file
end

View File

@@ -0,0 +1,35 @@
Puppet::Type.newtype(:ceilometer_pipeline_section) do
ensurable do
defaultvalues
defaultto :present
end
newparam(:name) do
desc 'The unique name of the resource'
isnamevar
end
newparam(:path) do
validate do |value|
fail 'The path should be absolute!' unless Puppet::Util.absolute_path? value
end
end
newparam(:array_name) do
desc 'The name of the array to search section in'
defaultto { 'sources' }
end
newparam(:section_name) do
desc 'The name of the section to update'
defaultto { 'contrail_source' }
end
newparam(:data) do
desc 'Directly pass the section structure'
validate do |value|
fail 'The data structure should be a hash!' unless value.is_a? Hash
end
end
end

View File

@@ -1,21 +0,0 @@
Puppet::Type.newtype(:merge_yaml_settings) do
desc = "Type to merge yaml configuration files"
ensurable
newparam(:name)
newparam(:path) do
desc "Path for destination settings file"
end
newparam(:sample_settings) do
desc "Path or Hash containing source settings"
end
newparam(:override_settings) do
desc "Path or Hash containing custom settings"
end
end

View File

@@ -261,13 +261,23 @@ class contrail::controller {
if ($ceilometer_enabled) {
package { 'ceilometer-plugin-contrail': } ->
merge_yaml_settings { 'contrail_ceilometer_pipeline_yaml':
ensure => present,
path => '/etc/ceilometer/pipeline.yaml',
sample_settings => '/etc/ceilometer/pipeline.yaml',
override_settings => $custom_yaml_settings,
require => Package['ceilometer-plugin-contrail'],
ceilometer_pipeline_section { 'contrail_ceilometer_pipeline_yaml_source' :
ensure => 'present',
path => '/etc/ceilometer/pipeline.yaml',
data => $custom_yaml_settings['sources'],
section_name => 'contrail_source',
array_name => 'sources',
} ->
ceilometer_pipeline_section { 'contrail_ceilometer_pipeline_yaml_sink' :
ensure => 'present',
path => '/etc/ceilometer/pipeline.yaml',
data => $custom_yaml_settings['sinks'],
section_name => 'contrail_sink',
array_name => 'sinks',
}
if $contrail::ceilometer_ha_mode {
service {'ceilometer-agent-central':
ensure => running,
@@ -276,7 +286,7 @@ class contrail::controller {
hasstatus => true,
hasrestart => true,
provider => 'pacemaker',
subscribe => Merge_yaml_settings['contrail_ceilometer_pipeline_yaml'],
tag => 'ceilometer',
}
}
else {
@@ -284,14 +294,14 @@ class contrail::controller {
service { 'ceilometer-polling':
ensure => running,
enable => true,
subscribe => Merge_yaml_settings['contrail_ceilometer_pipeline_yaml'],
tag => 'ceilometer',
}
}
if !defined(Service['ceilometer-api']) {
service { 'ceilometer-api':
ensure => running,
enable => true,
subscribe => Merge_yaml_settings['contrail_ceilometer_pipeline_yaml'],
tag => 'ceilometer',
}
}
}
@@ -299,4 +309,6 @@ class contrail::controller {
Contrailplugin_ini_config<||> ~> File['/etc/neutron/plugin.ini']
Heat_config<||> ~> Service['heat-engine']
Nova_config<||> ~> Service['nova-api']
Ceilometer_pipeline_section <||> ~>
Service <| tag == 'ceilometer' |>
}

View File

@@ -0,0 +1,12 @@
require 'puppetlabs_spec_helper/module_spec_helper'
require 'puppet'
RSpec.configure do |config|
config.mock_framework = :rspec
end
def puppet_debug_override
return unless ENV['SPEC_PUPPET_DEBUG']
Puppet::Util::Log.level = :debug
Puppet::Util::Log.newdestination(:console)
end

View File

@@ -0,0 +1,61 @@
require 'spec_helper'
describe Puppet::Type.type(:ceilometer_pipeline_section).provider(:ruby) do
let(:section_data) do
{
'name' => 'contrail_source',
'a' => '1',
'b' => {
'c' => [1, 2, 3],
'd' => '2',
}
}
end
let(:resource) do
Puppet::Type.type(:ceilometer_pipeline_section).new(
:name => 'test',
:path => '/tmp/test.yaml',
:data => section_data,
:provider => :ruby,
)
end
let(:provider) do
resource.provider
end
subject { provider }
it { is_expected.not_to be_nil }
def get_source(data, name)
data['sources'].find { |host| host['name'] == name }
end
context 'data modification' do
it 'can add a new section with a custom data' do
data = {'sources' => []}
subject.modify_section data
expect(get_source data, 'contrail_source').to eq(section_data)
end
it 'can update the existing section with a custom data' do
data = {
'sources' => [
{
'name' => 'contrail_source',
'a' => '1',
}
]
}
subject.modify_section data
expect(get_source data, 'contrail_source').to eq(section_data)
end
end
end

View File

@@ -0,0 +1,32 @@
require 'spec_helper'
describe Puppet::Type.type(:ceilometer_pipeline_section) do
subject do
Puppet::Type.type(:ceilometer_pipeline_section)
end
it 'should exist' do
is_expected.not_to be_nil
end
describe 'basic structure' do
it 'should be able to create an instance' do
expect(subject.new(
:name => 'test',
:path => '/tmp/test.yaml',
)).to_not be_nil
end
[:name, :path, :array_name, :section_name, :data].each do |param|
it "should have a #{param} parameter" do
expect(subject.validparameter?(param)).to be_truthy
end
it "should have documentation for its #{param} parameter" do
expect(subject.paramclass(param).doc).to be_a String
end
end
end
end