From dce599e49898d7973805a389d3abf5048f9f5099 Mon Sep 17 00:00:00 2001 From: Flavio Fernandes Date: Mon, 24 Feb 2020 16:01:48 -0500 Subject: [PATCH] Add Octavia OVN Provider configuration (1 of 2) This patch enhances Octavia's OVN driver config, so it can connect to OVN_Northbound DB using TLS. This is part 1 of 2, where octavia::api::ovn_nb_connection will move to newly created octavia::provider::ovn::ovn_nb_connection config file. But that has to be split into 2 parts to avoid breaking the CI until the THT+pupple-tripleo changes merges [1]. [1]: https://review.opendev.org/#/q/topic:bug/1861886+(status:open+OR+status:merged) Co-Authored-By: Brent Eagles Related-Bug: #1861886 Change-Id: Id74ef39ff303c9abf8118df203970cd871ed974a --- .../ini_setting.rb | 10 +++ .../type/octavia_ovn_provider_config.rb | 53 +++++++++++++++ manifests/provider/ovn.pp | 45 ++++++++++++ .../add-ovn-provider-71b506e3d81e92fe.yaml | 4 ++ spec/classes/octavia_ovn_provider_spec.rb | 47 +++++++++++++ .../ini_setting_spec.rb | 68 +++++++++++++++++++ .../type/octavia_ovn_provider_config_spec.rb | 64 +++++++++++++++++ 7 files changed, 291 insertions(+) create mode 100644 lib/puppet/provider/octavia_ovn_provider_config/ini_setting.rb create mode 100644 lib/puppet/type/octavia_ovn_provider_config.rb create mode 100644 manifests/provider/ovn.pp create mode 100644 releasenotes/notes/add-ovn-provider-71b506e3d81e92fe.yaml create mode 100644 spec/classes/octavia_ovn_provider_spec.rb create mode 100644 spec/unit/provider/octavia_ovn_provider_config/ini_setting_spec.rb create mode 100644 spec/unit/type/octavia_ovn_provider_config_spec.rb diff --git a/lib/puppet/provider/octavia_ovn_provider_config/ini_setting.rb b/lib/puppet/provider/octavia_ovn_provider_config/ini_setting.rb new file mode 100644 index 00000000..1ea095b5 --- /dev/null +++ b/lib/puppet/provider/octavia_ovn_provider_config/ini_setting.rb @@ -0,0 +1,10 @@ +Puppet::Type.type(:octavia_ovn_provider_config).provide( + :ini_setting, + :parent => Puppet::Type.type(:openstack_config).provider(:ini_setting) +) do + + def self.file_path + '/etc/octavia/conf.d/ovn.conf' + end + +end diff --git a/lib/puppet/type/octavia_ovn_provider_config.rb b/lib/puppet/type/octavia_ovn_provider_config.rb new file mode 100644 index 00000000..297eda3c --- /dev/null +++ b/lib/puppet/type/octavia_ovn_provider_config.rb @@ -0,0 +1,53 @@ +Puppet::Type.newtype(:octavia_ovn_provider_config) do + + ensurable + + newparam(:name, :namevar => true) do + desc 'Section/setting name to manage from conf.d/ovn.conf' + newvalues(/\S+\/\S+/) + end + + newproperty(:value) do + desc 'The value of the setting to be defined.' + munge do |value| + value = value.to_s.strip + value.capitalize! if value =~ /^(true|false)$/i + value + end + newvalues(/^[\S ]*$/) + + def is_to_s( currentvalue ) + if resource.secret? + return '[old secret redacted]' + else + return currentvalue + end + end + + def should_to_s( newvalue ) + if resource.secret? + return '[new secret redacted]' + else + return newvalue + end + end + end + + newparam(:secret, :boolean => true) do + desc 'Whether to hide the value from Puppet logs. Defaults to `false`.' + + newvalues(:true, :false) + + defaultto false + end + + newparam(:ensure_absent_val) do + desc 'A value that is specified as the value property will behave as if ensure => absent was specified' + defaultto('') + end + + autorequire(:package) do + 'octavia' + end + +end diff --git a/manifests/provider/ovn.pp b/manifests/provider/ovn.pp new file mode 100644 index 00000000..740aaa74 --- /dev/null +++ b/manifests/provider/ovn.pp @@ -0,0 +1,45 @@ +# Configures the octavia ovn driver +# +# == Parameters +# +# [*ovn_nb_connection*] +# (optional) The connection string for the OVN_Northbound OVSDB. +# Defaults to $::os_service_default +# +# [*ovn_nb_private_key*] +# (optional) The PEM file with private key for SSL connection to OVN-NB-DB +# Defaults to $::os_service_default +# +# [*ovn_nb_certificate*] +# (optional) The PEM file with certificate that certifies the private +# key specified in ovn_nb_private_key +# Defaults to $::os_service_default +# +# [*ovn_nb_ca_cert*] +# (optional) The PEM file with CA certificate that OVN should use to +# verify certificates presented to it by SSL peers +# Defaults to $::os_service_default +# +class octavia::provider::ovn ( + $ovn_nb_connection = $::os_service_default, + $ovn_nb_private_key = $::os_service_default, + $ovn_nb_certificate = $::os_service_default, + $ovn_nb_ca_cert = $::os_service_default +) inherits octavia::params { + + include octavia::deps + + # For backward compatibility + if $::octavia::api::ovn_nb_connection and !is_service_default($::octavia::api::ovn_nb_connection) { + $ovn_nb_connection_real = $::octavia::api::ovn_nb_connection + } else { + $ovn_nb_connection_real = $ovn_nb_connection + } + + octavia_ovn_provider_config { + 'ovn/ovn_nb_connection': value => $ovn_nb_connection_real; + 'ovn/ovn_nb_private_key': value => $ovn_nb_private_key; + 'ovn/ovn_nb_certificate': value => $ovn_nb_certificate; + 'ovn/ovn_nb_ca_cert': value => $ovn_nb_ca_cert; + } +} diff --git a/releasenotes/notes/add-ovn-provider-71b506e3d81e92fe.yaml b/releasenotes/notes/add-ovn-provider-71b506e3d81e92fe.yaml new file mode 100644 index 00000000..fbbb0b10 --- /dev/null +++ b/releasenotes/notes/add-ovn-provider-71b506e3d81e92fe.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Added octavia::provider::ovn for configuring OVN driver properties. diff --git a/spec/classes/octavia_ovn_provider_spec.rb b/spec/classes/octavia_ovn_provider_spec.rb new file mode 100644 index 00000000..07205659 --- /dev/null +++ b/spec/classes/octavia_ovn_provider_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe 'octavia::provider::ovn' do + + let :params do + { + } + end + + shared_examples_for 'octavia-ovn-provider' do + + context 'with default parameters' do + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_connection').with_value('') } + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_private_key').with_value('') } + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_certificate').with_value('') } + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_ca_cert').with_value('') } + end + + context 'with specific parameters' do + before do + params.merge!({ + :ovn_nb_connection => 'tcp:127.0.0.1:6641', + :ovn_nb_private_key => '/foo.key', + :ovn_nb_certificate => '/foo.pem', + :ovn_nb_ca_cert => '/ca_foo.pem' + }) + end + + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_connection').with_value('tcp:127.0.0.1:6641') } + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_private_key').with_value('/foo.key') } + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_certificate').with_value('/foo.pem') } + it { is_expected.to contain_octavia_ovn_provider_config('ovn/ovn_nb_ca_cert').with_value('/ca_foo.pem') } + end + end + + on_supported_os({ + :supported_os => OSDefaults.get_supported_os + }).each do |os,facts| + context "on #{os}" do + let (:facts) do + facts.merge!(OSDefaults.get_facts()) + end + it_behaves_like 'octavia-ovn-provider' + end + end + +end diff --git a/spec/unit/provider/octavia_ovn_provider_config/ini_setting_spec.rb b/spec/unit/provider/octavia_ovn_provider_config/ini_setting_spec.rb new file mode 100644 index 00000000..0c2574f3 --- /dev/null +++ b/spec/unit/provider/octavia_ovn_provider_config/ini_setting_spec.rb @@ -0,0 +1,68 @@ +# +# these tests are a little concerning b/c they are hacking around the +# modulepath, so these tests will not catch issues that may eventually arise +# related to loading these plugins. +# I could not, for the life of me, figure out how to programatcally set the modulepath +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'inifile', + 'lib') +) +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'openstacklib', + 'lib') +) +require 'spec_helper' +provider_class = Puppet::Type.type(:octavia_ovn_provider_config).provider(:ini_setting) +describe provider_class do + + it 'should default to the default setting when no other one is specified' do + resource = Puppet::Type::Octavia_ovn_provider_config.new( + {:name => 'DEFAULT/foo', :value => 'bar'} + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('DEFAULT') + expect(provider.setting).to eq('foo') + end + + it 'should allow setting to be set explicitly' do + resource = Puppet::Type::Octavia_ovn_provider_config.new( + {:name => 'dude/foo', :value => 'bar'} + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('dude') + expect(provider.setting).to eq('foo') + end + + it 'should ensure absent when is specified as a value' do + resource = Puppet::Type::Octavia_ovn_provider_config.new( + {:name => 'dude/foo', :value => ''} + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + + it 'should ensure absent when value matches ensure_absent_val' do + resource = Puppet::Type::Octavia_ovn_provider_config.new( + {:name => 'dude/foo', :value => 'foo', :ensure_absent_val => 'foo' } + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + +end diff --git a/spec/unit/type/octavia_ovn_provider_config_spec.rb b/spec/unit/type/octavia_ovn_provider_config_spec.rb new file mode 100644 index 00000000..5af91433 --- /dev/null +++ b/spec/unit/type/octavia_ovn_provider_config_spec.rb @@ -0,0 +1,64 @@ +require 'puppet' +require 'puppet/type/octavia_ovn_provider_config' +describe 'Puppet::Type.type(:octavia_ovn_provider_config)' do + before :each do + @octavia_ovn_provider_config = Puppet::Type.type(:octavia_ovn_provider_config).new(:name => 'DEFAULT/foo', :value => 'bar') + end + + it 'should require a name' do + expect { + Puppet::Type.type(:octavia_ovn_provider_config).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + it 'should not expect a name with whitespace' do + expect { + Puppet::Type.type(:octavia_ovn_provider_config).new(:name => 'f oo') + }.to raise_error(Puppet::Error, /Parameter name failed/) + end + + it 'should fail when there is no section' do + expect { + Puppet::Type.type(:octavia_ovn_provider_config).new(:name => 'foo') + }.to raise_error(Puppet::Error, /Parameter name failed/) + end + + it 'should not require a value when ensure is absent' do + Puppet::Type.type(:octavia_ovn_provider_config).new(:name => 'DEFAULT/foo', :ensure => :absent) + end + + it 'should accept a valid value' do + @octavia_ovn_provider_config[:value] = 'bar' + expect(@octavia_ovn_provider_config[:value]).to eq('bar') + end + + it 'should not accept a value with whitespace' do + @octavia_ovn_provider_config[:value] = 'b ar' + expect(@octavia_ovn_provider_config[:value]).to eq('b ar') + end + + it 'should accept valid ensure values' do + @octavia_ovn_provider_config[:ensure] = :present + expect(@octavia_ovn_provider_config[:ensure]).to eq(:present) + @octavia_ovn_provider_config[:ensure] = :absent + expect(@octavia_ovn_provider_config[:ensure]).to eq(:absent) + end + + it 'should not accept invalid ensure values' do + expect { + @octavia_ovn_provider_config[:ensure] = :latest + }.to raise_error(Puppet::Error, /Invalid value/) + end + + it 'should autorequire the package that install the file' do + catalog = Puppet::Resource::Catalog.new + package = Puppet::Type.type(:package).new(:name => 'octavia') + catalog.add_resource package, @octavia_ovn_provider_config + dependency = @octavia_ovn_provider_config.autorequire + expect(dependency.size).to eq(1) + expect(dependency[0].target).to eq(@octavia_ovn_provider_config) + expect(dependency[0].source).to eq(package) + end + + +end