From da32b883b3f3624230e1b97cca09a1848112ddfc Mon Sep 17 00:00:00 2001 From: Stanislav Makar Date: Wed, 4 Nov 2015 16:48:55 +0000 Subject: [PATCH] Ovs2Lnx patch config saving for CentOS7/RHEL7 *Implement ovs2lnx patch config saving *Implement ovs bridge config saving (remove dirty hacks) *Test coverage Change-Id: I9f50a8ea3a7b4d7d03585375ac47069c6408c92a Closes-bug: #1513134 --- .../provider/l23_stored_config_centos.rb | 30 ++-- .../provider/l23_stored_config_ovs_centos.rb | 93 +++++++++--- .../provider/l23_stored_config_ubuntu.rb | 2 +- .../centos7_bridges/ifcfg-lnx-bridge | 4 + .../centos7_bridges/ifcfg-ovs-bridge | 6 + .../centos7_patches/ifcfg-ovs2lnx-patch | 7 + .../lnx_centos6__bridges_and_ports__spec.rb | 2 +- .../lnx_centos7__bridge__spec.rb | 92 ++++++++++++ .../lnx_centos7__bridges_and_ports__spec.rb | 2 +- .../lnx_redhat7__bridges_and_ports__spec.rb | 2 +- .../ovs_centos7__bridge__spec.rb | 96 +++++++++++++ .../ovs_centos7__ovs2lnx_patch__spec.rb | 134 ++++++++++++++++++ 12 files changed, 439 insertions(+), 31 deletions(-) create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-lnx-bridge create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-ovs-bridge create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_patches/ifcfg-ovs2lnx-patch create mode 100644 deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridge__spec.rb create mode 100644 deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__bridge__spec.rb create mode 100644 deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__ovs2lnx_patch__spec.rb diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb index cadb083516..5c69593425 100644 --- a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb @@ -129,6 +129,11 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ hash.delete('PREFIX') end + hash.delete('DEVICETYPE') if hash['DEVICETYPE'] + + # Do extra actions if ovs2lnx patch cord + hash = self.parse_patch_bridges(hash) if ( hash.has_key?('BRIDGE') and hash.has_key?('OVS_BRIDGE') ) + hash = self.parse_bond_opts(hash) if ( hash.has_key?('TYPE') and hash['TYPE'] =~ %r{Bond} ) props = self.mangle_properties(hash) @@ -143,6 +148,11 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ raise Puppet::Error, "self.check_if_provider(if_data) Should be implemented in more specific class." end + def self.parse_patch_bridges(hash) + # Do nothing, this is only needed for ovs provider + hash + end + def self.parse_bond_opts(hash) if hash.has_key?('BONDING_OPTS') bonding_opts_line = hash['BONDING_OPTS'].gsub('"', '').split(' ') @@ -207,7 +217,8 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ end def self.mangle__method(val) - (['manual', 'static'].include? val.to_s.downcase) ? :none : val.to_sym + val = 'manual' if val.to_s == 'none' + val.to_s.downcase end def self.mangle__ethtool(val) @@ -267,10 +278,7 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ property_mappings.keys.select{|v| ! properties_fake.include?(v)}.each do |type_name| val = provider.send(type_name) - if val.is_a?(Array) - val.select { |x| x.to_s != 'absent' or x.to_s != '' } - val = false if val.empty? - end + next if ( val.is_a?(Array) and val.reject{ |x| x.to_s == 'absent' }.empty? ) if val and val.to_s != 'absent' props[type_name] = val end @@ -283,14 +291,15 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ props[:slave] = 'yes' end + # Do extra actions if ovs2lnx patch cord + props = self.format_patch_bridges(props) if ( props[:if_type].to_s == 'vport' and props[:bridge].size > 1 ) + props = self.format_bond_opts(props) if props.has_key?(:bond_mode) debug("format_file('#{filename}')::properties: #{props.inspect}") pairs = self.unmangle_properties(provider, props) - if pairs['TYPE'] == :OVSBridge - pairs['DEVICETYPE'] = 'ovs' - end + pairs['DEVICETYPE'] = 'ovs' if pairs['TYPE'].to_s =~ /OVS/ if pairs['ROUTES'] route_filename = "#{self.script_directory}/route-#{provider.name}" @@ -331,6 +340,11 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ self.write_file file, content end + def self.format_patch_bridges(props) + # Do nothing, this is only needed for ovs provider + props + end + def self.format_bond_opts(props) bond_options = [] bond_properties = property_mappings.select { |k, v| k.to_s =~ %r{bond_.*} and !([:bond_master].include?(k)) } diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ovs_centos.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ovs_centos.rb index b2852f7693..00151733ed 100644 --- a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ovs_centos.rb +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ovs_centos.rb @@ -7,6 +7,7 @@ class Puppet::Provider::L23_stored_config_ovs_centos < Puppet::Provider::L23_sto rv.merge!({ :devicetype => 'DEVICETYPE', :bridge => 'OVS_BRIDGE', + :lnx_bridge => 'BRIDGE', :bond_slaves => 'BOND_IFACES', :bonding_opts => 'OVS_OPTIONS', :bond_mode => 'bond_mode', @@ -24,21 +25,63 @@ class Puppet::Provider::L23_stored_config_ovs_centos < Puppet::Provider::L23_sto def self.properties_fake rv = super rv.push(:devicetype) + rv.push(:lnx_bridge) return rv end - #Dirty hack which writes config files for OVS - #bridges into /tmp directory - def select_file - if name == 'br-prv' or name == 'br-floating' - "/tmp/ifcfg-#{name}" - else - "#{self.class.script_directory}/ifcfg-#{name}" + def self.get_catalog + return unless @all_providers + first_provider = @all_providers.first + return unless first_provider + class << first_provider + attr_reader :resource + end + first_provider_resource = first_provider.resource + first_provider_resource.catalog + end + + def self.resource_in_catalog(type,title) + catalog = get_catalog + return unless catalog + catalog.resources.find do |res| + res.type == type.to_sym and res.name == title end end + def self.provider_of(title) + # This function is finding out the provider of bridge + found_resource = resource_in_catalog :l23_stored_config, title + return unless found_resource + found_resource.provider.class.name + end + + def self.format_patch_bridges(props) + bridges = props[:bridge] + raise Puppet::Error, %{Patch #{props[:name]} has more than 2 bridges: #{bridges}. Patch can connect *ONLY* 2 bridges!} if bridges.size >2 + lnx_bridge = [] + ovs_bridge = [] + bridges.each do |bridge| + bridge_provider = provider_of(bridge) + if bridge_provider.to_s =~ /lnx_centos/ + lnx_bridge << bridge + elsif bridge_provider.to_s =~ /ovs_centos/ + ovs_bridge << bridge + else + raise Puppet::Error, %{Patch #{props[:name]}: the bridge #{bridge} provider #{bridge_provider} is not supported!} + end + end + if lnx_bridge.size > ovs_bridge.size + provider_problem = lnx_bridge + elsif ovs_bridge.size > lnx_bridge.size + provider_problem = ovs_bridge + end + raise Puppet::Error, %{Patch #{props[:name]} has the same provider bridges: #{provider_problem} !} if provider_problem + props[:lnx_bridge] = lnx_bridge + props[:bridge] = ovs_bridge + props + end + def self.format_bond_opts(props) - props[:devicetype] = 'ovs' bond_options = [] bond_properties = property_mappings.select { |k, v| k.to_s =~ %r{bond_.*} and !([:bond_slaves].include?(k)) } bond_properties.each do |param, transform | @@ -51,6 +94,12 @@ class Puppet::Provider::L23_stored_config_ovs_centos < Puppet::Provider::L23_sto props end + def self.parse_patch_bridges(hash) + hash['OVS_BRIDGE'] = [hash['OVS_BRIDGE'], hash['BRIDGE']].join(' ') + hash.delete('BRIDGE') + hash + end + def self.parse_bond_opts(hash) pair_regex = %r/^\s*(.+?)\s*=\s*(.*)\s*$/ if hash.has_key?('OVS_OPTIONS') @@ -68,11 +117,15 @@ class Puppet::Provider::L23_stored_config_ovs_centos < Puppet::Provider::L23_sto end def self.unmangle__if_type(provider, val) - "OVS#{val.to_s.capitalize}".to_sym + val = "OVS#{val.to_s.capitalize}".to_sym + val = 'OVSIntPort' if val.to_s == 'OVSVport' + val end def self.mangle__if_type(val) - val.gsub('OVS', '').downcase.to_sym + val = val.gsub('OVS', '').downcase.to_sym + val = :vport if val.to_s == 'intport' + val end def self.unmangle__bond_slaves(provider, val) @@ -83,18 +136,20 @@ class Puppet::Provider::L23_stored_config_ovs_centos < Puppet::Provider::L23_sto val.split(' ') end - - #Dirty hack which deletes OVS bridges from patch OVS - #interfaces - def self.unmangle__bridge(provider, val) - if val.length == 2 - val.delete('br-prv') if val.include?('br-prv') - val.delete('br-floating') if val.include?('br-floating') - val - end + def self.unmangle__lnx_bridge(provider, val) val.join() end + def self.unmangle__bridge(provider, val) + val.join() + end + + def self.mangle__bridge(val) + val.split(' ') + end + + + end # vim: set ts=2 sw=2 et : diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb index a96bf931b4..197155f80d 100644 --- a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb @@ -402,7 +402,7 @@ class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_ property_mappings.reject{|k,v| (properties_fake.include?(k) or v.empty?)}.keys.each do |type_name| next if props.has_key? type_name val = provider.send(type_name) - val = false if ( val.is_a?(Array) and val.reject{ |x| x.to_s == 'absent' }.empty? ) + next if ( val.is_a?(Array) and val.reject{ |x| x.to_s == 'absent' }.empty? ) if val and val.to_s != 'absent' props[type_name] = val end diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-lnx-bridge b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-lnx-bridge new file mode 100644 index 0000000000..affd86a3e6 --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-lnx-bridge @@ -0,0 +1,4 @@ +BOOTPROTO=none +DEVICE=lnx-bridge +ONBOOT=yes +TYPE=Bridge diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-ovs-bridge b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-ovs-bridge new file mode 100644 index 0000000000..569aeb1d4a --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_bridges/ifcfg-ovs-bridge @@ -0,0 +1,6 @@ +BOOTPROTO=none +DEVICE=ovs-bridge +ONBOOT=yes +MTU=9000 +TYPE=OVSBridge +DEVICETYPE=ovs diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_patches/ifcfg-ovs2lnx-patch b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_patches/ifcfg-ovs2lnx-patch new file mode 100644 index 0000000000..89b988e5c7 --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/centos7_patches/ifcfg-ovs2lnx-patch @@ -0,0 +1,7 @@ +BOOTPROTO=none +DEVICE=ovs2lnx-patch +ONBOOT=yes +TYPE=OVSIntPort +OVS_BRIDGE=ovs-br +BRIDGE=lnx-br +DEVICETYPE=ovs diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos6__bridges_and_ports__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos6__bridges_and_ports__spec.rb index 5bfb26fb4b..6780538c9c 100644 --- a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos6__bridges_and_ports__spec.rb +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos6__bridges_and_ports__spec.rb @@ -74,7 +74,7 @@ describe Puppet::Type.type(:l23_stored_config).provider(:lnx_centos6) do context "the method property" do context 'when dhcp' do let(:data) { subject.class.parse_file('eth0', fixture_data('ifcfg-eth0'))[0] } - it { expect(data[:method]).to eq :dhcp } + it { expect(data[:method]).to eq 'dhcp' } end end diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridge__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridge__spec.rb new file mode 100644 index 0000000000..141b7bfff0 --- /dev/null +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridge__spec.rb @@ -0,0 +1,92 @@ +require 'spec_helper' +require 'yaml' + +describe Puppet::Type.type(:l23_stored_config).provider(:lnx_centos7) do + + let(:facts) do + { + :osfamily => 'Redhat', + :operatingsystem => 'CentOS', + :l23_os => 'centos7', + } + end + + let(:input_data) do + { + :ovs_bridge => { + :name => 'lnx-bridge', + :ensure => 'present', + :if_type => 'bridge', + :onboot => true, + :method => 'manual', + :provider => 'lnx_centos7', + }, + } + end + + let(:resources) do + resources = {} + input_data.each do |name, res| + resources.store name, Puppet::Type.type(:l23_stored_config).new(res) + end + return resources + end + + let(:providers) do + providers = {} + resources.each do |name, resource| + provider = resource.provider + if ENV['SPEC_PUPPET_DEBUG'] + class << provider + def debug(msg) + puts msg + end + end + end + provider.create + providers.store name, provider + end + providers + end + + before(:each) do + puppet_debug_override() + end + + def fixture_path + File.join(PROJECT_ROOT, 'spec', 'fixtures', 'provider', 'l23_stored_config', 'centos7_bridges') + end + + def fixture_file(file) + File.join(fixture_path, file) + end + + def fixture_data(file) + File.read(fixture_file(file)) + end + + context "OVS bridge" do + + context 'format file' do + subject { providers[:ovs_bridge] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(%r{DEVICE=lnx-bridge}) } + it { expect(cfg_file).to match(%r{BOOTPROTO=none}) } + it { expect(cfg_file).to match(%r{ONBOOT=yes}) } + it { expect(cfg_file).to match(%r{TYPE=Bridge}) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(4) } # no more lines in the interface file + + end + + context "parse bridge data from fixture" do + let(:res) { subject.class.parse_file('lnx-bridge', fixture_data('ifcfg-lnx-bridge'))[0] } + it { expect(res[:name]).to eq 'lnx-bridge' } + it { expect(res[:if_type].to_s).to eq 'bridge' } + it { expect(res[:method].to_s).to eq 'manual' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:provider]).to eq :lnx_centos7 } + end + + end + +end diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridges_and_ports__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridges_and_ports__spec.rb index 58c1e9fd47..068140d178 100644 --- a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridges_and_ports__spec.rb +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__bridges_and_ports__spec.rb @@ -74,7 +74,7 @@ describe Puppet::Type.type(:l23_stored_config).provider(:lnx_centos7) do context "the method property" do context 'when dhcp' do let(:data) { subject.class.parse_file('eth0', fixture_data('ifcfg-eth0'))[0] } - it { expect(data[:method]).to eq :dhcp } + it { expect(data[:method]).to eq 'dhcp' } end end diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_redhat7__bridges_and_ports__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_redhat7__bridges_and_ports__spec.rb index 168853f44c..12c8b65a99 100644 --- a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_redhat7__bridges_and_ports__spec.rb +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_redhat7__bridges_and_ports__spec.rb @@ -74,7 +74,7 @@ describe Puppet::Type.type(:l23_stored_config).provider(:lnx_redhat7) do context "the method property" do context 'when dhcp' do let(:data) { subject.class.parse_file('eth0', fixture_data('ifcfg-eth0'))[0] } - it { expect(data[:method]).to eq :dhcp } + it { expect(data[:method]).to eq 'dhcp' } end end diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__bridge__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__bridge__spec.rb new file mode 100644 index 0000000000..757cd5333a --- /dev/null +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__bridge__spec.rb @@ -0,0 +1,96 @@ +require 'spec_helper' +require 'yaml' + +describe Puppet::Type.type(:l23_stored_config).provider(:ovs_centos7) do + + let(:facts) do + { + :osfamily => 'Redhat', + :operatingsystem => 'CentOS', + :l23_os => 'centos7', + } + end + + let(:input_data) do + { + :ovs_bridge => { + :name => 'ovs-bridge', + :ensure => 'present', + :if_type => 'bridge', + :mtu => '9000', + :onboot => true, + :method => 'manual', + :provider => 'ovs_centos7', + }, + } + end + + let(:resources) do + resources = {} + input_data.each do |name, res| + resources.store name, Puppet::Type.type(:l23_stored_config).new(res) + end + return resources + end + + let(:providers) do + providers = {} + resources.each do |name, resource| + provider = resource.provider + if ENV['SPEC_PUPPET_DEBUG'] + class << provider + def debug(msg) + puts msg + end + end + end + provider.create + providers.store name, provider + end + providers + end + + before(:each) do + puppet_debug_override() + end + + def fixture_path + File.join(PROJECT_ROOT, 'spec', 'fixtures', 'provider', 'l23_stored_config', 'centos7_bridges') + end + + def fixture_file(file) + File.join(fixture_path, file) + end + + def fixture_data(file) + File.read(fixture_file(file)) + end + + context "OVS bridge" do + + context 'format file' do + subject { providers[:ovs_bridge] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(%r{DEVICE=ovs-bridge}) } + it { expect(cfg_file).to match(%r{BOOTPROTO=none}) } + it { expect(cfg_file).to match(%r{ONBOOT=yes}) } + it { expect(cfg_file).to match(%r{TYPE=OVSBridge}) } + it { expect(cfg_file).to match(%r{MTU=9000}) } + it { expect(cfg_file).to match(%r{DEVICETYPE=ovs}) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(6) } # no more lines in the interface file + + end + + context "parse bridge data from fixture" do + let(:res) { subject.class.parse_file('ovs-bridge', fixture_data('ifcfg-ovs-bridge'))[0] } + it { expect(res[:name]).to eq 'ovs-bridge' } + it { expect(res[:if_type].to_s).to eq 'bridge' } + it { expect(res[:method].to_s).to eq 'manual' } + it { expect(res[:mtu]).to eq '9000' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:provider]).to eq :ovs_centos7 } + end + + end + +end diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__ovs2lnx_patch__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__ovs2lnx_patch__spec.rb new file mode 100644 index 0000000000..52ef04f048 --- /dev/null +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/ovs_centos7__ovs2lnx_patch__spec.rb @@ -0,0 +1,134 @@ +require 'spec_helper' +require 'yaml' + +describe Puppet::Type.type(:l23_stored_config).provider(:ovs_centos7) do + + let(:facts) do + { + :osfamily => 'Redhat', + :operatingsystem => 'CentOS', + :l23_os => 'centos7', + } + end + + let(:input_data) do + { + :ovs2lnx_patch => { + :name => 'ovs2lnx-patch', + :ensure => 'present', + :if_type => 'vport', + :bridge => ['ovs-br', 'lnx-br'], + :onboot => true, + :method => 'manual', + :provider => 'ovs_centos7', + }, + :ovs2lnx_bad_patch => { + :name => 'ovs2lnx-bpatch', + :ensure => 'present', + :if_type => 'vport', + :bridge => ['ovs-br', 'lnx-br', 'br-fake'], + :onboot => true, + :method => 'manual', + :provider => 'ovs_centos7', + }, + :ovs2lnx_bad_patch2 => { + :name => 'ovs2lnx-bpatch2', + :ensure => 'present', + :if_type => 'vport', + :bridge => ['ovs-br1', 'ovs-br2'], + :onboot => true, + :method => 'manual', + :provider => 'ovs_centos7', + }, + + + } + end + + let(:resources) do + resources = {} + input_data.each do |name, res| + resources.store name, Puppet::Type.type(:l23_stored_config).new(res) + end + return resources + end + + let(:providers) do + providers = {} + resources.each do |name, resource| + provider = resource.provider + if ENV['SPEC_PUPPET_DEBUG'] + class << provider + def debug(msg) + puts msg + end + end + end + provider.create + providers.store name, provider + end + providers + end + + before(:each) do + puppet_debug_override() + subject.class.stubs(:provider_of).with('ovs-br').returns('ovs_centos7') + subject.class.stubs(:provider_of).with('lnx-br').returns('lnx_centos7') + subject.class.stubs(:provider_of).with('ovs-br1').returns('ovs_centos7') + subject.class.stubs(:provider_of).with('ovs-br2').returns('ovs_centos7') + end + + def fixture_path + File.join(PROJECT_ROOT, 'spec', 'fixtures', 'provider', 'l23_stored_config', 'centos7_patches') + end + + def fixture_file(file) + File.join(fixture_path, file) + end + + def fixture_data(file) + File.read(fixture_file(file)) + end + + context "ovs2lnx patch" do + + context 'format patch file' do + subject { providers[:ovs2lnx_patch] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(%r{DEVICE=ovs2lnx-patch}) } + it { expect(cfg_file).to match(%r{BOOTPROTO=none}) } + it { expect(cfg_file).to match(%r{ONBOOT=yes}) } + it { expect(cfg_file).to match(%r{TYPE=OVSIntPort}) } + it { expect(cfg_file).to match(%r{BRIDGE=lnx-br}) } + it { expect(cfg_file).to match(%r{OVS_BRIDGE=ovs-br}) } + it { expect(cfg_file).to match(%r{DEVICETYPE=ovs}) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(7) } # no more lines in the interface file + + end + + context 'three bridges patch error' do + subject { providers[:ovs2lnx_bad_patch] } + it { expect{ subject.class.format_file('filepath', [subject]) + }.to raise_error(Puppet::Error, %r{Patch\s+ovs2lnx-bpatch\s+has\s+more\s+than\s+2\s+bridges:\s+\["ovs-br",\s+"lnx-br",\s+"br-fake"].\s+Patch\s+can\s+connect\s+\*ONLY\*\s+2\s+bridges!}) } + end + + context 'the same provider of bridges error' do + subject { providers[:ovs2lnx_bad_patch2] } + it { expect{ subject.class.format_file('filepath', [subject]) + }.to raise_error(Puppet::Error, %r{Patch\s+ovs2lnx-bpatch2\s+has\s+the\s+same\s+provider\s+bridges:\s+\["ovs-br1",\s+"ovs-br2"\]\s+!}) } + end + + + context "parse patch data from fixture" do + let(:res) { subject.class.parse_file('ovs2lnx-patch', fixture_data('ifcfg-ovs2lnx-patch'))[0] } + it { expect(res[:name]).to eq 'ovs2lnx-patch' } + it { expect(res[:if_type].to_s).to eq 'vport' } + it { expect(res[:bridge]).to match_array(['lnx-br', 'ovs-br']) } + it { expect(res[:method].to_s).to eq 'manual' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:provider].to_s).to eq 'ovs_centos7' } + end + + end + +end