(MODULES-11173) Add per-host overrides for apt::proxy
authormaturnbull <89206484+maturnbull@users.noreply.github.com>
Mon, 23 Aug 2021 19:54:20 +0000 (20:54 +0100)
committermaturnbull <89206484+maturnbull@users.noreply.github.com>
Wed, 25 Aug 2021 21:20:46 +0000 (22:20 +0100)
Add support for optional apt::proxy::perhost array to configure bypass (DIRECT) or alternative proxy for specific repository hosts.

REFERENCE.md
manifests/init.pp
spec/classes/apt_spec.rb
templates/proxy.epp
types/proxy.pp
types/proxy_per_host.pp [new file with mode: 0644]

index 3a3e9a8447cca140e50cc4400240c5a7cb499106..674ec22f05176bcbc7ae548c67b5c33808a3404d 100644 (file)
@@ -41,6 +41,7 @@ be manipulated through the `apt-key` command.
 
 * [`Apt::Auth_conf_entry`](#aptauth_conf_entry): Login configuration settings that are recorded in the file `/etc/apt/auth.conf`.
 * [`Apt::Proxy`](#aptproxy): Configures Apt to connect to a proxy server.
+* [`Apt::Proxy_Per_Host`](#aptproxy_per_host): Adds per-host overrides to the system default APT proxy configuration
 
 ### Tasks
 
@@ -1099,6 +1100,7 @@ Struct[{
     https      => Optional[Boolean],
     https_acng => Optional[Boolean],
     direct     => Optional[Boolean],
+    perhost    => Optional[Array[Apt::Proxy_Per_Host]],
   }]
 ```
 
@@ -1132,6 +1134,52 @@ Specifies whether to enable https proxies.
 
 Specifies whether or not to use a `DIRECT` https proxy if http proxy is used but https is not.
 
+### <a name="aptproxy_per_host"></a>`Apt::Proxy_Per_Host`
+
+Adds per-host overrides to the system default APT proxy configuration
+
+Alias of
+
+```puppet
+Struct[{
+    scope      => String,
+    host       => Optional[String],
+    port       => Optional[Integer[1, 65535]],
+    https      => Optional[Boolean],
+    direct     => Optional[Boolean],
+  }]
+```
+
+#### Parameters
+
+The following parameters are available in the `Apt::Proxy_Per_Host` data type:
+
+* [`scope`](#scope)
+* [`host`](#host)
+* [`port`](#port)
+* [`https`](#https)
+* [`direct`](#direct)
+
+##### <a name="scope"></a>`scope`
+
+Specifies the scope of the override.  Valid options: a string containing a hostname.
+
+##### <a name="host"></a>`host`
+
+Specifies a proxy host to be stored in `/etc/apt/apt.conf.d/01proxy`. Valid options: a string containing a hostname.
+
+##### <a name="port"></a>`port`
+
+Specifies a proxy port to be stored in `/etc/apt/apt.conf.d/01proxy`. Valid options: an integer containing a port number.
+
+##### <a name="https"></a>`https`
+
+Specifies whether to enable https for this override.
+
+##### <a name="direct"></a>`direct`
+
+Specifies whether or not to use a `DIRECT` target to bypass the system default proxy.
+
 ## Tasks
 
 ### <a name="init"></a>`init`
index fdfd600781b9fb2cfbbedf10ff2a6de1451499b5..49f93093ce99396695fc64f922fb21a9772247e9 100644 (file)
@@ -204,7 +204,29 @@ class apt (
   }
 
   $_purge = merge($::apt::purge_defaults, $purge)
-  $_proxy = merge($apt::proxy_defaults, $proxy)
+
+  if $proxy['perhost'] {
+    $_perhost = $proxy['perhost'].map |$item| {
+      $_item = merge($apt::proxy_defaults, $item)
+      $_scheme = $_item['https'] ? {
+        true    => 'https',
+        default => 'http' }
+      $_port = $_item['port'] ? {
+        Integer => ":${_item['port']}",
+        default => ''
+      }
+      $_target = $_item['direct'] ? {
+        true    => 'DIRECT',
+        default => "${_scheme}://${_item['host']}${_port}/" }
+      merge($item, {
+        'scheme' => $_scheme,
+        'target' => $_target })
+    }
+  } else {
+    $_perhost = {}
+  }
+
+  $_proxy = merge($apt::proxy_defaults, $proxy, { 'perhost' => $_perhost } )
 
   $confheadertmp = epp('apt/_conf_header.epp')
   $proxytmp = epp('apt/proxy.epp', {'proxies' => $_proxy})
index ca23563f21b41261b825948faa9f0e601bc88da9..03b638ca7fbd1406ae1888578d8c2317d58e3738 100644 (file)
@@ -101,7 +101,69 @@ describe 'apt' do
         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
           %r{Acquire::http::proxy "http://localhost:8080/";},
         ).without_content(
-          %r{Acquire::https::proxy},
+          %r{Acquire::https::proxy },
+        )
+      }
+    end
+
+    context 'when host=localhost and per-host[proxyscope]=proxyhost' do
+      let(:params) { { proxy: { 'host' => 'localhost', 'perhost' => [{ 'scope' => 'proxyscope', 'host' => 'proxyhost' }] } } }
+
+      it {
+        is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
+          %r{Acquire::http::proxy::proxyscope "http://proxyhost:8080/";},
+        )
+      }
+    end
+
+    context 'when host=localhost and per-host[proxyscope]=proxyhost:8081' do
+      let(:params) { { proxy: { 'host' => 'localhost', 'perhost' => [{ 'scope' => 'proxyscope', 'host' => 'proxyhost', 'port' => 8081 }] } } }
+
+      it {
+        is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
+          %r{Acquire::http::proxy::proxyscope "http://proxyhost:8081/";},
+        )
+      }
+    end
+
+    context 'when host=localhost and per-host[proxyscope]=[https]proxyhost' do
+      let(:params) { { proxy: { 'host' => 'localhost', 'perhost' => [{ 'scope' => 'proxyscope', 'host' => 'proxyhost', 'https' => true }] } } }
+
+      it {
+        is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
+          %r{Acquire::https::proxy::proxyscope "https://proxyhost:8080/";},
+        )
+      }
+    end
+
+    context 'when host=localhost and per-host[proxyscope]=[direct]' do
+      let(:params) { { proxy: { 'host' => 'localhost', 'perhost' => [{ 'scope' => 'proxyscope', 'direct' => true }] } } }
+
+      it {
+        is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
+          %r{Acquire::http::proxy::proxyscope "DIRECT";},
+        )
+      }
+    end
+
+    context 'when host=localhost and per-host[proxyscope]=[https][direct]' do
+      let(:params) { { proxy: { 'host' => 'localhost', 'perhost' => [{ 'scope' => 'proxyscope', 'https' => true, 'direct' => true }] } } }
+
+      it {
+        is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
+          %r{Acquire::https::proxy::proxyscope "DIRECT";},
+        )
+      }
+    end
+
+    context 'when host=localhost and per-host[proxyscope]=proxyhost and per-host[proxyscope2]=proxyhost2' do
+      let(:params) { { proxy: { 'host' => 'localhost', 'perhost' => [{ 'scope' => 'proxyscope', 'host' => 'proxyhost' }, { 'scope' => 'proxyscope2', 'host' => 'proxyhost2' }] } } }
+
+      it {
+        is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
+          %r{Acquire::http::proxy::proxyscope "http://proxyhost:8080/";},
+        ).with_content(
+          %r{Acquire::http::proxy::proxyscope2 "http://proxyhost2:8080/";},
         )
       }
     end
@@ -113,7 +175,7 @@ describe 'apt' do
         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
           %r{Acquire::http::proxy "http://localhost:8180/";},
         ).without_content(
-          %r{Acquire::https::proxy},
+          %r{Acquire::https::proxy },
         )
       }
     end
index ee663cb82ea80ccfe15ffc90d0ec3c967188d06f..34e193076d00ece851c092d2c7c896c7123563ce 100644 (file)
@@ -1,4 +1,7 @@
 <%- | Hash $proxies | -%>
+<% $proxies['perhost'].each |$proxy| { -%>
+Acquire::<%= $proxy['scheme'] %>::proxy::<%= $proxy['scope'] %> "<%= $proxy['target'] %>";
+<% } -%>
 Acquire::http::proxy "http://<%= $proxies['host'] %>:<%= $proxies['port'] %>/";
 <%- if $proxies['https'] { %>
 Acquire::https::proxy "https://<%= $proxies['host'] %>:<%= $proxies['port'] %>/";
index 20cbfecf9a6d1af44ff9d4cb8d81b84d991061cf..ac00222f0800126a5150b536502719d0a184ef54 100644 (file)
@@ -23,5 +23,6 @@ type Apt::Proxy = Struct[
     https      => Optional[Boolean],
     https_acng => Optional[Boolean],
     direct     => Optional[Boolean],
+    perhost    => Optional[Array[Apt::Proxy_Per_Host]],
   }
 ]
diff --git a/types/proxy_per_host.pp b/types/proxy_per_host.pp
new file mode 100644 (file)
index 0000000..5a3b6e6
--- /dev/null
@@ -0,0 +1,26 @@
+# @summary Adds per-host overrides to the system default APT proxy configuration
+#
+# @param scope
+#   Specifies the scope of the override.  Valid options: a string containing a hostname.
+#
+# @param host
+#   Specifies a proxy host to be stored in `/etc/apt/apt.conf.d/01proxy`. Valid options: a string containing a hostname.
+#
+# @param port
+#   Specifies a proxy port to be stored in `/etc/apt/apt.conf.d/01proxy`. Valid options: an integer containing a port number.
+#
+# @param https
+#   Specifies whether to enable https for this override.
+#
+# @param direct
+#   Specifies whether or not to use a `DIRECT` target to bypass the system default proxy.
+#
+type Apt::Proxy_Per_Host = Struct[
+  {
+    scope      => String,
+    host       => Optional[String],
+    port       => Optional[Integer[1, 65535]],
+    https      => Optional[Boolean],
+    direct     => Optional[Boolean],
+  }
+]