Skip to content

Commit

Permalink
Add an apache::vhost::proxy define
Browse files Browse the repository at this point in the history
This builds on apache::vhost::fragment with a more specialized type for
a reverse proxy setup. This reuses the same template as apache::vhost
but has data types. The types are stricter, but this leads to a clearer
API. For example, it doesn't accept String and Array[String] but in that
case always wants an Array.

The old parameters on vhost remain and can continue to be used.
  • Loading branch information
ekohl authored and wbclark committed Jul 20, 2021
1 parent f50950a commit b5c28d6
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 0 deletions.
81 changes: 81 additions & 0 deletions manifests/vhost/proxy.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# @summary Configure a reverse reverse proxy for a vhost
#
# @param proxy_dest
# Specifies the destination address of a [ProxyPass](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration.
#
# @param proxy_pass
# Specifies an array of `path => URI` values for a [ProxyPass](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass)
# configuration. Optionally, parameters can be added as an array.
# ``` puppet
# apache::vhost { 'site.name.fdqn':
#
# proxy_pass => [
# { 'path' => '/a', 'url' => 'http://backend-a/' },
# { 'path' => '/b', 'url' => 'http://backend-b/' },
# { 'path' => '/c', 'url' => 'http://backend-a/c', 'params' => {'max'=>20, 'ttl'=>120, 'retry'=>300}},
# { 'path' => '/l', 'url' => 'http://backend-xy',
# 'reverse_urls' => ['http://backend-x', 'http://backend-y'] },
# { 'path' => '/d', 'url' => 'http://backend-a/d',
# 'params' => { 'retry' => '0', 'timeout' => '5' }, },
# { 'path' => '/e', 'url' => 'http://backend-a/e',
# 'keywords' => ['nocanon', 'interpolate'] },
# { 'path' => '/f', 'url' => 'http://backend-f/',
# 'setenv' => ['proxy-nokeepalive 1','force-proxy-request-1.0 1']},
# { 'path' => '/g', 'url' => 'http://backend-g/',
# 'reverse_cookies' => [{'path' => '/g', 'url' => 'http://backend-g/',}, {'domain' => 'http://backend-g', 'url' => 'http:://backend-g',},], },
# { 'path' => '/h', 'url' => 'http://backend-h/h',
# 'no_proxy_uris' => ['/h/admin', '/h/server-status'] },
# ],
# }
# ```
# * `reverse_urls`. *Optional.* This setting is useful when used with `mod_proxy_balancer`. Values: an array or string.
# * `reverse_cookies`. *Optional.* Sets `ProxyPassReverseCookiePath` and `ProxyPassReverseCookieDomain`.
# * `params`. *Optional.* Allows for ProxyPass key-value parameters, such as connection settings.
# * `setenv`. *Optional.* Sets [environment variables](https://httpd.apache.org/docs/current/mod/mod_proxy.html#envsettings) for the proxy directive. Values: array.
#
# @param proxy_dest_match
# This directive is equivalent to `proxy_dest`, but takes regular expressions, see
# [ProxyPassMatch](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassmatch)
# for details.
#
# @param proxy_dest_reverse_match
# Allows you to pass a ProxyPassReverse if `proxy_dest_match` is specified. See
# [ProxyPassReverse](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassreverse)
# for details.
#
# @param proxy_pass_match
# This directive is equivalent to `proxy_pass`, but takes regular expressions, see
# [ProxyPassMatch](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassmatch)
# for details.
define apache::vhost::proxy(
String[1] $vhost,
$priority = undef,
Integer[0] $order = 170,
Optional[Stdlib::Port] $port = undef,
Optional[String[1]] $proxy_dest = undef,
Optional[Array[Apache::Vhost::ProxyPass]] $proxy_pass = undef,
Optional[Array[Apache::Vhost::ProxyPass]] $proxy_pass_match = undef,
Optional[String[1]] $proxy_dest_match = undef,
Optional[String[1]] $proxy_dest_reverse_match = undef,
Boolean $proxy_requests = false,
Boolean $proxy_preserve_host = false,
Optional[Boolean] $proxy_add_headers = undef,
Boolean $proxy_error_override = false,
Variant[Array[String[1]], String[1]] $no_proxy_uris = [],
Variant[Array[String[1]], String[1]] $no_proxy_uris_match = [],
) {
include apache::mod::proxy
include apache::mod::proxy_http

unless $proxy_dest or $proxy_pass or $proxy_pass_match or $proxy_dest_match {
fail('At least one of proxy_dest, proxy_pass, proxy_pass_match or proxy_dest_match must be given')
}

apache::vhost::fragment { "${name}-proxy":
vhost => $vhost,
port => $port,
priority => $priority,
order => $order,
content => template('apache/vhost/_proxy.erb'),
}
}
49 changes: 49 additions & 0 deletions spec/defines/vhost_proxy_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'apache::vhost::proxy' do
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:facts) { os_facts }
let(:title) { 'myproxy' }

context 'adding to the default vhost' do
let(:pre_condition) { 'include apache' }

let(:params) do
{
vhost: 'default',
port: 80,
priority: '15',
}
end

context 'without any parameters' do
it { is_expected.to compile.and_raise_error(/At least one of/) }
end

context 'with proxy_dest' do
let(:params) { super().merge( proxy_pass: [{ path: '/', url: 'http://localhost:8080/' }] )}

it 'creates a concat fragment' do
is_expected.to compile.with_all_deps
is_expected.to contain_concat('15-default-80.conf')
is_expected.to create_concat__fragment('default-myproxy-proxy')
.with_target('15-default-80.conf')
.with_order(170)
.with_content(<<CONTENT
## Proxy rules
ProxyRequests Off
ProxyPreserveHost Off
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
CONTENT
)
end
end
end
end
end
end
16 changes: 16 additions & 0 deletions types/vhost/proxypass.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# @summary A proxy pass definition for in an Apache vhost
type Apache::Vhost::ProxyPass = Struct[{
path => String[1],
url => String[1],
Optional[params] => Hash[String[1], Variant[String[1], Integer]],
Optional[keywords] => Array[String[1]],
Optional[reverse_cookies] => Array[Struct[{
url => String[1],
path => Optional[String[1]],
domain => Optional[String[1]],
}]],
Optional[reverse_urls] => Array[String[1]],
Optional[setenv] => Array[String[1]],
Optional[no_proxy_uris] => Array[String[1]],
Optional[no_proxy_uris_match] => Array[String[1]],
}]

0 comments on commit b5c28d6

Please sign in to comment.