Support customizing internal-client.conf

This change introduces capability to customize internal-client.conf,
which is used by several daemon processes like container-sharder.

Closes-Bug: #1986599
Related-Bug: #1921319
Change-Id: I200e3a4ff323a07778ec6c4d7dd96824c72a12cf
This commit is contained in:
Takashi Kajinami 2022-07-18 11:47:09 +09:00
parent dd88f5625d
commit efcef86de7
17 changed files with 615 additions and 0 deletions

View File

@ -0,0 +1,10 @@
Puppet::Type.type(:swift_internal_client_config).provide(
:ini_setting,
:parent => Puppet::Type.type(:openstack_config).provider(:ini_setting)
) do
def self.file_path
'/etc/swift/internal-client.conf'
end
end

View File

@ -0,0 +1,53 @@
Puppet::Type.newtype(:swift_internal_client_config) do
ensurable
newparam(:name, :namevar => true) do
desc 'Section/setting name to manage from /etc/swift/internal-client.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('<SERVICE DEFAULT>')
end
autorequire(:anchor) do
['swift::install::end']
end
end

View File

@ -28,10 +28,16 @@
# (optional) Allow configuration of arbitrary Swift Proxy configurations.
# The value is an hash of swift_proxy_config resources.
#
# [*swift_internal_client_config*]
# (optional) Allow configuration of arbitrary Swift internal client
# configurations.
# The value is an hash of swift_internal_client_config resources.
#
class swift::config (
$swift_config = {},
$swift_container_sync_realms_config = {},
$swift_proxy_config = {},
$swift_internal_client_config = {},
) {
include swift::deps
@ -39,8 +45,10 @@ class swift::config (
validate_legacy(Hash, 'validate_hash', $swift_config)
validate_legacy(Hash, 'validate_hash', $swift_container_sync_realms_config)
validate_legacy(Hash, 'validate_hash', $swift_proxy_config)
validate_legacy(Hash, 'validate_hash', $swift_internal_client_config)
create_resources('swift_config', $swift_config)
create_resources('swift_container_sync_realms_config', $swift_container_sync_realms_config)
create_resources('swift_proxy_config', $swift_proxy_config)
create_resources('swift_internal_client_config', $swift_internal_client_config)
}

View File

@ -41,6 +41,10 @@ class swift::deps {
-> Swift_account_config<||>
~> Anchor['swift::config::end']
Anchor['swift::config::begin']
-> Swift_internal_client_config<||>
~> Anchor['swift::config::end']
Anchor['swift::config::begin']
-> File<| tag == 'swift-file' |>
-> Concat<| tag == 'swift-concat' |>

View File

@ -0,0 +1,95 @@
# == Class: swift::internal_client
#
# Configures internal client
#
# === Parameters
#
# [*user*]
# (optional) User to run as
# Defaults to $::swift::params::user.
#
# [*pipeline*]
# (optional) The list of elements of the internal client pipeline.
# Defaults to ['catch_errors', 'proxy-logging', 'cache', 'proxy-server']
#
# [*object_chunk_size*]
# (optional) Chunk size to read from object servers.
# Defaults to $::os_service_default.
#
# [*client_chunk_size*]
# (optional) Chunk size to read from clients.
# Defaults to $::os_service_default.
#
# [*read_affinity*]
# (optional) Configures the read affinity of internal client.
# Defaults to undef.
#
# [*write_affinity*]
# (optional) Configures the write affinity of internal client.
# Defaults to $::os_service_default.
#
# [*write_affinity_node_count*]
# (optional) Configures write_affinity_node_count for internal client.
# Optional but requires write_affinity to be set.
# Defaults to $::os_service_default.
#
# [*client_timeout*]
# (optional) Configures client_timeout for internal client.
# Defaults to $::os_service_default.
#
# [*node_timeout*]
# (optional) Configures node_timeout for internal client.
# Defaults to $::os_service_default.
#
# [*recoverable_node_timeout*]
# (optional) Configures recoverable_node_timeout for internal client.
# Defaults to $::os_service_default.
#
class swift::internal_client (
$user = $::swift::params::user,
$pipeline = ['catch_errors', 'proxy-logging', 'cache', 'proxy-server'],
$object_chunk_size = $::os_service_default,
$client_chunk_size = $::os_service_default,
$read_affinity = undef,
$write_affinity = $::os_service_default,
$write_affinity_node_count = $::os_service_default,
$client_timeout = $::os_service_default,
$node_timeout = $::os_service_default,
$recoverable_node_timeout = $::os_service_default,
) inherits swift::params {
include swift::deps
validate_legacy(Array, 'validate_array', $pipeline)
if(! member($pipeline, 'proxy-server')) {
warning('pipeline parameter must contain proxy-server')
}
swift_internal_client_config {
'DEFAULT/user': value => $user;
'pipeline:main/pipeline': value => join($pipeline, ' ');
'app:proxy-server/use': value => 'egg:swift#proxy';
'app:proxy-server/account_autocreate': value => true;
'app:proxy-server/object_chunk_size': value => $object_chunk_size;
'app:proxy-server/client_chunk_size': value => $client_chunk_size;
'app:proxy-server/write_affinity': value => $write_affinity;
'app:proxy-server/write_affinity_node_count': value => $write_affinity_node_count;
'app:proxy-server/client_timeout': value => $client_timeout;
'app:proxy-server/node_timeout': value => $node_timeout;
'app:proxy-server/recoverable_node_timeout': value => $recoverable_node_timeout;
}
if $read_affinity {
swift_internal_client_config {
'app:proxy-server/sorting_method': value => 'affinity';
'app:proxy-server/read_affinity': value => $read_affinity;
}
} else {
swift_internal_client_config {
'app:proxy-server/sorting_method': value => $::os_service_default;
'app:proxy-server/read_affinity': value => $::os_service_default;
}
}
}

View File

@ -0,0 +1,76 @@
#
# Configures the swift proxy memcache server
#
# [*memcache_servers*] A list of the memcache servers to be used. Entries
# should be in the form host:port.
#
# [*tls_enabled*]
# (Optional) Global toggle for TLS usage when communicating with
# the caching servers.
# Default to false
#
# [*tls_cafile*]
# (Optional) Path to a file of concatenated CA certificates in PEM
# format necessary to establish the caching server's authenticity.
# If tls_enabled is False, this option is ignored.
# Defaults to undef
#
# [*tls_certfile*]
# (Optional) Path to a single file in PEM format containing the
# client's certificate as well as any number of CA certificates
# needed to establish the certificate's authenticity. This file
# is only required when client side authentication is necessary.
# If tls_enabled is False, this option is ignored.
# Defaults to undef
#
# [*tls_keyfile*]
# (Optional) Path to a single file containing the client's private
# key in. Otherwise the private key will be taken from the file
# specified in tls_certfile. If tls_enabled is False, this option
# is ignored.
# Defaults to undef
#
# [*memcache_max_connections*] Sets the maximum number of connections to
# each memcached server per worker
#
# == Dependencies
#
# Class['memcached']
#
# == Examples
#
# == Authors
#
# Dan Bode dan@puppetlabs.com
#
# == Copyright
#
# Copyright 2011 Puppetlabs Inc, unless otherwise noted.
#
class swift::internal_client::cache(
$memcache_servers = ['127.0.0.1:11211'],
$tls_enabled = false,
$tls_cafile = undef,
$tls_certfile = undef,
$tls_keyfile = undef,
$memcache_max_connections = '2'
) {
include swift::deps
# require the memcached class if its on the same machine
if !empty(grep(any2array($memcache_servers), '127.0.0.1')) {
Class['memcached'] -> Class['swift::internal_client::cache']
}
swift_internal_client_config {
'filter:cache/use': value => 'egg:swift#memcache';
'filter:cache/memcache_servers': value => join(any2array($memcache_servers), ',');
'filter:cache/tls_enabled': value => $tls_enabled;
'filter:cache/tls_cafile': value => $tls_cafile;
'filter:cache/tls_certfile': value => $tls_certfile;
'filter:cache/tls_keyfile': value => $tls_keyfile;
'filter:cache/memcache_max_connections': value => $memcache_max_connections;
}
}

View File

@ -0,0 +1,25 @@
#
# Configure swift cache_errors.
#
# == Dependencies
#
# == Examples
#
# include swift::internal_client::catch_errors
#
# == Authors
#
# Francois Charlier fcharlier@ploup.net
#
# == Copyright
#
# Copyright 2012 eNovance licensing@enovance.com
#
class swift::internal_client::catch_errors() {
include swift::deps
swift_internal_client_config {
'filter:catch_errors/use': value => 'egg:swift#catch_errors';
}
}

View File

@ -0,0 +1,15 @@
#
# Configure swift proxy-logging.
#
# == Authors
#
# Joe Topjian joe@topjian.net
#
class swift::internal_client::proxy_logging {
include swift::deps
swift_internal_client_config {
'filter:proxy-logging/use': value => 'egg:swift#proxy_logging';
}
}

View File

@ -0,0 +1,42 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Configure swift symlink middleware.
#
# == Example
#
# include swift::internal_client::symlink
#
# == Parameters
#
# [*symloop_max*]
# Symlinks can point to other symlinks provided the number of symlinks in a
# chain does not exceed the symloop_max value. If the number of chained
# symlinks exceeds the limit symloop_max a 409 (HTTPConflict) error
# response will be produced.
# Default to $::os_service_default
#
# == Authors
#
# shi.yan@ardc.edu.au
#
class swift::internal_client::symlink(
$symloop_max = $::os_service_default,
) {
include swift::deps
swift_internal_client_config {
'filter:symlink/use': value => 'egg:swift#symlink';
'filter:symlink/symloop_max': value => $symloop_max;
}
}

View File

@ -0,0 +1,5 @@
---
features:
- |
Now this module supports configurion options in
`/etc/swift/internal-client.conf``.

View File

@ -11,6 +11,11 @@ describe 'swift::config' do
'DEFAULT/foo' => { 'value' => 'fooValue' },
'DEFAULT/bar' => { 'value' => 'barValue' },
'DEFAULT/baz' => { 'ensure' => 'absent' }
},
:swift_internal_client_config => {
'DEFAULT/foo' => { 'value' => 'fooValue' },
'DEFAULT/bar' => { 'value' => 'barValue' },
'DEFAULT/baz' => { 'ensure' => 'absent' }
}
}
end
@ -27,6 +32,12 @@ describe 'swift::config' do
is_expected.to contain_swift_proxy_config('DEFAULT/bar').with_value('barValue')
is_expected.to contain_swift_proxy_config('DEFAULT/baz').with_ensure('absent')
end
it 'configures arbitrary swift internal client configurations' do
is_expected.to contain_swift_internal_client_config('DEFAULT/foo').with_value('fooValue')
is_expected.to contain_swift_internal_client_config('DEFAULT/bar').with_value('barValue')
is_expected.to contain_swift_internal_client_config('DEFAULT/baz').with_ensure('absent')
end
end
on_supported_os({

View File

@ -0,0 +1,78 @@
require 'spec_helper'
describe 'swift::internal_client::cache' do
shared_examples 'swift::internal_client::cache' do
describe 'without memcached being included' do
it 'should raise an error' do
expect { catalogue }.to raise_error(Puppet::Error)
end
end
describe 'with memcached dependency' do
let :pre_condition do
'class { "memcached": max_memory => 1 }'
end
describe 'with defaults' do
it 'should have the required classes' do
is_expected.to contain_class('swift::deps')
is_expected.to contain_class('swift::internal_client::cache')
end
it { is_expected.to contain_swift_internal_client_config('filter:cache/use').with_value('egg:swift#memcache') }
it { is_expected.to contain_swift_internal_client_config('filter:cache/memcache_servers').with_value('127.0.0.1:11211') }
it { is_expected.to contain_swift_internal_client_config('filter:cache/tls_enabled').with_value(false) }
it { is_expected.to contain_swift_internal_client_config('filter:cache/memcache_max_connections').with_value(2) }
end
describe 'with overridden memcache server' do
let :params do
{:memcache_servers => '10.0.0.1:1'}
end
it { is_expected.to contain_swift_internal_client_config('filter:cache/use').with_value('egg:swift#memcache') }
it { is_expected.to contain_swift_internal_client_config('filter:cache/memcache_servers').with_value('10.0.0.1:1') }
end
describe 'with overridden memcache server array' do
let :params do
{:memcache_servers => ['10.0.0.1:1', '10.0.0.2:2']}
end
it { is_expected.to contain_swift_internal_client_config('filter:cache/use').with_value('egg:swift#memcache') }
it { is_expected.to contain_swift_internal_client_config('filter:cache/memcache_servers').with_value('10.0.0.1:1,10.0.0.2:2') }
end
describe 'with overridden cache TLS enabled' do
let :params do
{:tls_enabled => true}
end
it { is_expected.to contain_swift_internal_client_config('filter:cache/use').with_value('egg:swift#memcache') }
it { is_expected.to contain_swift_internal_client_config('filter:cache/tls_enabled').with_value(true) }
end
describe 'with overridden memcache max connections' do
let :params do
{:memcache_max_connections => 4}
end
it { is_expected.to contain_swift_internal_client_config('filter:cache/use').with_value('egg:swift#memcache') }
it { is_expected.to contain_swift_internal_client_config('filter:cache/memcache_max_connections').with_value(4) }
end
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_configures 'swift::internal_client::cache'
end
end
end

View File

@ -0,0 +1,19 @@
require 'spec_helper'
describe 'swift::internal_client::catch_errors' do
shared_examples 'swift::internal_client::catch_errors' do
it { should contain_swift_internal_client_config('filter:catch_errors/use').with_value('egg:swift#catch_errors') }
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_configures 'swift::internal_client::catch_errors'
end
end
end

View File

@ -0,0 +1,73 @@
require 'spec_helper'
describe 'swift::internal_client' do
shared_examples 'swift::internal_client' do
let :pre_condition do
"class { memcached: max_memory => 1}
class { swift: swift_hash_path_suffix => string }
include swift::internal_client::catch_errors
include swift::internal_client::proxy_logging
include swift::internal_client::cache"
end
context 'with defaults' do
it 'should configure default values' do
should contain_swift_internal_client_config('DEFAULT/user').with_value('swift')
should contain_swift_internal_client_config('pipeline:main/pipeline').with_value('catch_errors proxy-logging cache proxy-server')
should contain_swift_internal_client_config('app:proxy-server/use').with_value('egg:swift#proxy')
should contain_swift_internal_client_config('app:proxy-server/account_autocreate').with_value(true)
should contain_swift_internal_client_config('app:proxy-server/object_chunk_size').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/client_chunk_size').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/sorting_method').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/read_affinity').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/write_affinity').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/write_affinity_node_count').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/client_timeout').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/node_timeout').with_value('<SERVICE DEFAULT>')
should contain_swift_internal_client_config('app:proxy-server/recoverable_node_timeout').with_value('<SERVICE DEFAULT>')
end
end
context 'with parameters' do
let :params do
{
:pipeline => ['catch_errors', 'proxy-logging', 'proxy-server'],
:object_chunk_size => 65536,
:client_chunk_size => 65535,
:read_affinity => 'r1z1=100, r1=200',
:write_affinity => 'r1',
:write_affinity_node_count => '2 * replicas',
:client_timeout => '120',
:node_timeout => '20',
:recoverable_node_timeout => '15',
}
end
it 'should configure the given values' do
should contain_swift_internal_client_config('pipeline:main/pipeline').with_value('catch_errors proxy-logging proxy-server')
should contain_swift_internal_client_config('app:proxy-server/object_chunk_size').with_value(65536)
should contain_swift_internal_client_config('app:proxy-server/client_chunk_size').with_value(65535)
should contain_swift_internal_client_config('app:proxy-server/sorting_method').with_value('affinity')
should contain_swift_internal_client_config('app:proxy-server/read_affinity').with_value('r1z1=100, r1=200')
should contain_swift_internal_client_config('app:proxy-server/write_affinity').with_value('r1')
should contain_swift_internal_client_config('app:proxy-server/write_affinity_node_count').with_value('2 * replicas')
should contain_swift_internal_client_config('app:proxy-server/client_timeout').with_value('120')
should contain_swift_internal_client_config('app:proxy-server/node_timeout').with_value('20')
should contain_swift_internal_client_config('app:proxy-server/recoverable_node_timeout').with_value('15')
end
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 'swift::internal_client'
end
end
end

View File

@ -0,0 +1,33 @@
require 'spec_helper'
describe 'swift::internal_client::symlink' do
shared_examples 'swift::internal_client::symlink' do
context 'when using default parameters' do
it { is_expected.to contain_swift_internal_client_config('filter:symlink/use').with_value('egg:swift#symlink') }
it { is_expected.to contain_swift_internal_client_config('filter:symlink/symloop_max').with_value('<SERVICE DEFAULT>') }
end
context 'when overriding default parameters' do
let :params do
{
:symloop_max => '3'
}
end
it { is_expected.to contain_swift_internal_client_config('filter:symlink/use').with_value('egg:swift#symlink') }
it { is_expected.to contain_swift_internal_client_config('filter:symlink/symloop_max').with_value('3') }
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 'swift::internal_client::symlink'
end
end
end

View File

@ -0,0 +1,49 @@
require 'spec_helper'
provider_class = Puppet::Type.type(:swift_internal_client_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::Swift_internal_client_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::Swift_internal_client_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 <SERVICE DEFAULT> is specified as a value' do
resource = Puppet::Type::Swift_internal_client_config.new(
{:name => 'dude/foo', :value => '<SERVICE DEFAULT>'}
)
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::Swift_internal_client_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

View File

@ -0,0 +1,19 @@
require 'puppet'
require 'puppet/type/swift_internal_client_config'
describe 'Puppet::Type.type(:swift_internal_client_config)' do
before :each do
@swift_internal_client_config = Puppet::Type.type(:swift_internal_client_config).new(:name => 'DEFAULT/foo', :value => 'bar')
end
it 'should autorequire the package that install the file' do
catalog = Puppet::Resource::Catalog.new
anchor = Puppet::Type.type(:anchor).new(:name => 'swift::install::end')
catalog.add_resource anchor, @swift_internal_client_config
dependency = @swift_internal_client_config.autorequire
expect(dependency.size).to eq(1)
expect(dependency[0].target).to eq(@swift_internal_client_config)
expect(dependency[0].source).to eq(anchor)
end
end