mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
Merge pull request #3694 from fraenki/haproxy_4xx
net/haproxy: release 4.2 [only for 24.1]
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
PLUGIN_NAME= haproxy
|
||||
PLUGIN_VERSION= 4.1
|
||||
PLUGIN_REVISION= 1
|
||||
PLUGIN_VERSION= 4.2
|
||||
PLUGIN_COMMENT= Reliable, high performance TCP/HTTP load balancer
|
||||
PLUGIN_DEPENDS= haproxy26
|
||||
PLUGIN_DEPENDS= haproxy28 py${PLUGIN_PYTHON}-haproxy-cli
|
||||
PLUGIN_MAINTAINER= opnsense@moov.de
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
||||
|
||||
@@ -6,6 +6,30 @@ very high loads while needing persistence or Layer7 processing.
|
||||
Plugin Changelog
|
||||
================
|
||||
|
||||
4.2
|
||||
|
||||
Added:
|
||||
* add support for built-in OCSP update feature
|
||||
* add support for forwarded header (RFC7239)
|
||||
* add option "X-Forwarded-For Header" to backend settings
|
||||
* add options for HTTP/2 performance tuning
|
||||
|
||||
Fixed:
|
||||
* fix SSL sync cron job (bulk sync was never working properly)
|
||||
|
||||
Changed:
|
||||
* upgrade to HAProxy 2.8 release series (#3459)
|
||||
* change default for HTTP/2 to enabled (only new frontends/backends)
|
||||
* add "no-alpn" option if HTTP/2 is not enabled (only TLS-enabled frontends)
|
||||
* move OCSP settings from "Service" to "Global" section
|
||||
* replace bundled haproxyctl library with haproxy-cli
|
||||
|
||||
Deprecated:
|
||||
* frontend option "X-Forwarded-For Header" (the backend option should be used)
|
||||
|
||||
Removed:
|
||||
* remove OSCP update cron job
|
||||
|
||||
4.1
|
||||
|
||||
Fixed:
|
||||
|
||||
+6
-6
@@ -89,7 +89,7 @@
|
||||
<id>action.http_request_redirect</id>
|
||||
<label>HTTP Redirect</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Use HAProxy's redirect function to return a HTTP redirection. See <a href="http://docs.haproxy.org/2.6/configuration.html#redirect">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
<help><![CDATA[Use HAProxy's redirect function to return a HTTP redirection. See <a href="http://docs.haproxy.org/2.8/configuration.html#redirect">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Parameters</label>
|
||||
@@ -128,7 +128,7 @@
|
||||
<id>action.http_request_add_header_content</id>
|
||||
<label>Header Content</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it is possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.6/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it is possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.8/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Parameters</label>
|
||||
@@ -145,7 +145,7 @@
|
||||
<id>action.http_request_set_header_content</id>
|
||||
<label>Header Content</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it's possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.6/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it's possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.8/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Parameters</label>
|
||||
@@ -251,7 +251,7 @@
|
||||
<id>action.http_response_add_header_content</id>
|
||||
<label>Header Content</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it's possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.6/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it's possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.8/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Parameters</label>
|
||||
@@ -268,7 +268,7 @@
|
||||
<id>action.http_response_set_header_content</id>
|
||||
<label>Header Content</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it's possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.6/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
<help><![CDATA[The value that should be set for the specified HTTP header. Note that it's possible to use pre-defined variables, see <a href="http://docs.haproxy.org/2.8/configuration.html#8.2.4">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Parameters</label>
|
||||
@@ -468,6 +468,6 @@
|
||||
<id>action.fcgi_set_param</id>
|
||||
<label>Parameter</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Set a FastCGI parameter that should be passed to the application. Its value must follow HAProxy's <a href="http://docs.haproxy.org/2.6/configuration.html#8.2.4">Custom Log format rules</a>. With this directive, it is possible to overwrite the value of default FastCGI parameters.]]></help>
|
||||
<help><![CDATA[Set a FastCGI parameter that should be passed to the application. Its value must follow HAProxy's <a href="http://docs.haproxy.org/2.8/configuration.html#8.2.4">Custom Log format rules</a>. With this directive, it is possible to overwrite the value of default FastCGI parameters.]]></help>
|
||||
</field>
|
||||
</form>
|
||||
|
||||
+26
-5
@@ -28,7 +28,7 @@
|
||||
<id>backend.algorithm</id>
|
||||
<label>Balancing Algorithm</label>
|
||||
<type>dropdown</type>
|
||||
<help><![CDATA[Define the load balancing algorithm to be used in a Backend Pool. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#balance">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[Define the load balancing algorithm to be used in a Backend Pool. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#balance">HAProxy documentation</a> for a full description.]]></help>
|
||||
<hint>Choose a load balancing algorithm.</hint>
|
||||
</field>
|
||||
<field>
|
||||
@@ -42,7 +42,7 @@
|
||||
<id>backend.proxyProtocol</id>
|
||||
<label>Proxy Protocol</label>
|
||||
<type>dropdown</type>
|
||||
<help><![CDATA[Enforces use of the PROXY protocol over any connection established to the configured servers. The PROXY protocol informs the other end about the layer 3/4 addresses of the incoming connection, so that it can know the client's address or the public address it accessed to, whatever the upper layer protocol. This setting must not be used if the servers are not aware of the PROXY protocol. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#send-proxy">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[Enforces use of the PROXY protocol over any connection established to the configured servers. The PROXY protocol informs the other end about the layer 3/4 addresses of the incoming connection, so that it can know the client's address or the public address it accessed to, whatever the upper layer protocol. This setting must not be used if the servers are not aware of the PROXY protocol. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#send-proxy">HAProxy documentation</a> for a full description.]]></help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
@@ -173,6 +173,27 @@
|
||||
<sortable>true</sortable>
|
||||
<help><![CDATA[When using the TLS ALPN extension, HAProxy advertises the specified protocol list as supported on top of ALPN. TLS must be enabled.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>backend.forwardedHeader</id>
|
||||
<label>Forwarded header (RFC7239)</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Enable insertion of the RFC7239 forwarded header in requests sent to servers.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>backend.forwardedHeaderParameters</id>
|
||||
<label>Forwarded header parameters</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<allownew>true</allownew>
|
||||
<sortable>true</sortable>
|
||||
<help><![CDATA[This may be used to add more information to the forwarded header. Default behavior enables proto parameter and injects original client IP. See he <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#option forwarded">HAProxy documentation</a> for a full description.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>backend.forwardFor</id>
|
||||
<label>X-Forwarded-For header</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Enable insertion of the X-Forwarded-For header to requests sent to servers.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Persistence</label>
|
||||
<type>header</type>
|
||||
@@ -192,7 +213,7 @@
|
||||
<id>backend.persistence_cookiemode</id>
|
||||
<label>Cookie handling</label>
|
||||
<type>dropdown</type>
|
||||
<help><![CDATA[Usually it is better to reuse an existing cookie. In this case HAProxy prefixes the cookie with the required information. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#4.2-cookie">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[Usually it is better to reuse an existing cookie. In this case HAProxy prefixes the cookie with the required information. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#4.2-cookie">HAProxy documentation</a> for a full description.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>backend.persistence_cookiename</id>
|
||||
@@ -214,14 +235,14 @@
|
||||
<id>backend.stickiness_pattern</id>
|
||||
<label>Table type</label>
|
||||
<type>dropdown</type>
|
||||
<help><![CDATA[Choose a request pattern to associate a user to a server. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#stick on">HAProxy documentation</a> for a full description.<br/><div class="text-info"><b>NOTE:</b> Consider not using this feature in multi-process mode, it can result in random behaviours.</div>]]></help>
|
||||
<help><![CDATA[Choose a request pattern to associate a user to a server. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#stick on">HAProxy documentation</a> for a full description.<br/><div class="text-info"><b>NOTE:</b> Consider not using this feature in multi-process mode, it can result in random behaviours.</div>]]></help>
|
||||
<hint>Choose a persistence type.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>backend.stickiness_dataTypes</id>
|
||||
<label>Stored data types</label>
|
||||
<type>select_multiple</type>
|
||||
<help><![CDATA[This is used to store additional information in the stick-table. It may be used by ACLs in order to control various criteria related to the activity of the client matching the stick-table. Note that this directly impacts memory usage. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#stick-table">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[This is used to store additional information in the stick-table. It may be used by ACLs in order to control various criteria related to the activity of the client matching the stick-table. Note that this directly impacts memory usage. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#stick-table">HAProxy documentation</a> for a full description.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>backend.stickiness_expire</id>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<id>fcgi.path_info</id>
|
||||
<label>Path Info</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Define a regular expression to extract the script-name and the path-info from the URL-decoded path, see <a href="http://docs.haproxy.org/2.6/configuration.html#10.1.1-path-info">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
<help><![CDATA[Define a regular expression to extract the script-name and the path-info from the URL-decoded path, see <a href="http://docs.haproxy.org/2.8/configuration.html#10.1.1-path-info">HAProxy's documentation</a> for further details and examples.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>fcgi.log_stderr</id>
|
||||
|
||||
+5
-5
@@ -207,9 +207,9 @@
|
||||
</field>
|
||||
<field>
|
||||
<id>frontend.forwardFor</id>
|
||||
<label>X-Forwarded-For header</label>
|
||||
<label>X-Forwarded-For (DEPRECATED)</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Enable insertion of the X-Forwarded-For header to requests sent to servers.]]></help>
|
||||
<help><![CDATA[This option is DEPRECATED and should no longer be used. A new option is available in backend pool settings.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>frontend.prometheus_enabled</id>
|
||||
@@ -350,14 +350,14 @@
|
||||
<id>frontend.stickiness_pattern</id>
|
||||
<label>Table type</label>
|
||||
<type>dropdown</type>
|
||||
<help><![CDATA[Choose the type of data that should be stored in this stick-table. Note that this stick-table cannot be used for session persistence, it is only used to store additional per-connection data (select below). See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#stick-table">HAProxy documentation</a> for further information.]]></help>
|
||||
<help><![CDATA[Choose the type of data that should be stored in this stick-table. Note that this stick-table cannot be used for session persistence, it is only used to store additional per-connection data (select below). See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#stick-table">HAProxy documentation</a> for further information.]]></help>
|
||||
<hint>Choose a stick-table type.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>frontend.stickiness_dataTypes</id>
|
||||
<label>Stored data types</label>
|
||||
<type>select_multiple</type>
|
||||
<help><![CDATA[This is used to store additional information in the stick-table. It may be used by ACLs in order to control various criteria related to the activity of the client matching the stick-table. Note that this directly impacts memory usage. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#stick-table">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[This is used to store additional information in the stick-table. It may be used by ACLs in order to control various criteria related to the activity of the client matching the stick-table. Note that this directly impacts memory usage. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#stick-table">HAProxy documentation</a> for a full description.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>frontend.stickiness_expire</id>
|
||||
@@ -384,7 +384,7 @@
|
||||
<id>frontend.stickiness_counter_key</id>
|
||||
<label>Sticky counter key</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[It describes what elements of the incoming request or connection will be analyzed, extracted, combined, and used to select which table entry to update the counters. Defaults to "src" to track elements of the source IP. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#tcp-request connection">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[It describes what elements of the incoming request or connection will be analyzed, extracted, combined, and used to select which table entry to update the counters. Defaults to "src" to track elements of the source IP. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#tcp-request connection">HAProxy documentation</a> for a full description.]]></help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
|
||||
+1
-1
@@ -15,6 +15,6 @@
|
||||
<id>mapfile.content</id>
|
||||
<label>Content</label>
|
||||
<type>textbox</type>
|
||||
<help><![CDATA[Paste the content of your map file here. See the <a target="_blank" href="http://docs.haproxy.org/2.6/configuration.html#map">HAProxy documentation</a> for a full description.]]></help>
|
||||
<help><![CDATA[Paste the content of your map file here. See the <a target="_blank" href="http://docs.haproxy.org/2.8/configuration.html#map">HAProxy documentation</a> for a full description.]]></help>
|
||||
</field>
|
||||
</form>
|
||||
|
||||
-6
@@ -33,12 +33,6 @@
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[HAProxy will handle service restarts in a way that no connections are dropped. This is the best restart mode, because it has no impact on user experience. That being said, there might be edge cases where seamless reloads lead to unexpected behaviour.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.storeOcsp</id>
|
||||
<label>Store OCSP responses</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Retrieve OCSP data everytime when starting or restarting HAProxy. For every certificate, the OCSP response will be fetched and stored in filesystem, and automatically picked-up by HAProxy on startup. However, depending on the number of certificates and other circumstances, this may noticeably increase the time required to start/restart the HAProxy service. Note that this only updates the OCSP responses once during start/restart, you need to setup a cron job to periodically update this data too.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.showIntro</id>
|
||||
<label>Show introduction pages</label>
|
||||
|
||||
@@ -67,6 +67,28 @@
|
||||
<help><![CDATA[These lines will be added to the global settings of to the HAProxy configuration file.<br/><div class="text-info"><b>NOTE:</b> The syntax will not be checked, use at your own risk!</div>]]></help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<label>SSL settings</label>
|
||||
<type>header</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.ocspUpdateEnabled</id>
|
||||
<label>Automatic OCSP updates</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Enable automatic OCSP response updates. Each OCSP response will be updated at least once an hour, and even more frequently if a given OCSP response has an expire date earlier than this one hour limit.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.ocspUpdateMinDelay</id>
|
||||
<label>Minimum OCSP Interval</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the minimum interval (in seconds) between two automatic updates of the same OCSP response.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.ocspUpdateMaxDelay</id>
|
||||
<label>Maximum OCSP Interval</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the maximum interval (in seconds) between two automatic updates of the same OCSP response.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>SSL default settings</label>
|
||||
<type>header</type>
|
||||
@@ -110,4 +132,44 @@
|
||||
<sortable>true</sortable>
|
||||
<help><![CDATA[Used to enforce or disable certain SSL options.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>HTTP/2 Performance</label>
|
||||
<type>header</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.h2_initialWindowSize</id>
|
||||
<label>Initial window size</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the default value for the HTTP/2 initial window size, on both incoming and outgoing connections. The default value is 65536.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.h2_initialWindowSizeOutgoing</id>
|
||||
<label>Initial window size (outgoing)</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the HTTP/2 initial window size for outgoing connections, which is the number of bytes the server can respond to before waiting for an acknowledgment from HAProxy.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.h2_initialWindowSizeIncoming</id>
|
||||
<label>Initial window size (incoming)</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the HTTP/2 initial window size for incoming connections, which is the number of bytes the client can upload before waiting for an acknowledgment from HAProxy.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.h2_maxConcurrentStreams</id>
|
||||
<label>Max concurrent streams</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the default HTTP/2 maximum number of concurrent streams per connection (i.e. the number of outstanding requests on a single connection). The default value is 100.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.h2_maxConcurrentStreamsOutgoing</id>
|
||||
<label>Max concurrent streams (outgoing)</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the HTTP/2 maximum number of concurrent streams per outgoing connection (i.e. the number of outstanding requests on a single connection to a server).]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.h2_maxConcurrentStreamsIncoming</id>
|
||||
<label>Max concurrent streams (incoming)</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Sets the HTTP/2 maximum number of concurrent streams per incoming connection (i.e. the number of outstanding requests on a single connection from a client).]]></help>
|
||||
</field>
|
||||
</form>
|
||||
|
||||
-11
@@ -10,17 +10,6 @@
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically sync SSL certificate changes into the running HAProxy service. This is most useful when using short-lived Let's Encrypt certificates, but changes to other certificates will also be synced. Note that when using the Let's Encrypt plugin, it is also possible to use an <a target="_blank" href="/ui/acmeclient/actions">Automation</a> instead of this cron job.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Update OCSP data for SSL certificates</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_updateOcsp</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.updateOcsp</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically fetch OCSP data for all configured SSL certificates. Note that OCSP support needs to be enabled in <a target="_blank" href="/ui/haproxy#general-settings">HAProxy service settings</a>.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Reload HAProxy service</label>
|
||||
<type>header</type>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<model>
|
||||
<mount>//OPNsense/HAProxy</mount>
|
||||
<version>4.0.0</version>
|
||||
<version>4.1.0</version>
|
||||
<description>the HAProxy load balancer</description>
|
||||
<items>
|
||||
<general>
|
||||
@@ -27,6 +27,7 @@
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</seamlessReload>
|
||||
<!-- XXX: old value, required for model migration to 4.1.0 -->
|
||||
<storeOcsp type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
@@ -128,6 +129,24 @@
|
||||
<customOptions type="TextField">
|
||||
<Required>N</Required>
|
||||
</customOptions>
|
||||
<ocspUpdateEnabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</ocspUpdateEnabled>
|
||||
<ocspUpdateMinDelay type="IntegerField">
|
||||
<default>300</default>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>86400</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 1 and 86400.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</ocspUpdateMinDelay>
|
||||
<ocspUpdateMaxDelay type="IntegerField">
|
||||
<default>3600</default>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>86400</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 1 and 86400.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</ocspUpdateMaxDelay>
|
||||
<ssl_defaultsEnabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
@@ -182,6 +201,42 @@
|
||||
<default>TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256</default>
|
||||
<Required>N</Required>
|
||||
</ssl_cipherSuites>
|
||||
<h2_initialWindowSize type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>10000000</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 0 and 10000000.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</h2_initialWindowSize>
|
||||
<h2_initialWindowSizeOutgoing type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>10000000</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 0 and 10000000.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</h2_initialWindowSizeOutgoing>
|
||||
<h2_initialWindowSizeIncoming type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>10000000</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 0 and 10000000.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</h2_initialWindowSizeIncoming>
|
||||
<h2_maxConcurrentStreams type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>10000000</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 0 and 10000000.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</h2_maxConcurrentStreams>
|
||||
<h2_maxConcurrentStreamsOutgoing type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>10000000</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 0 and 10000000.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</h2_maxConcurrentStreamsOutgoing>
|
||||
<h2_maxConcurrentStreamsIncoming type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>10000000</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 0 and 10000000.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</h2_maxConcurrentStreamsIncoming>
|
||||
</tuning>
|
||||
<defaults>
|
||||
<maxConnections type="IntegerField">
|
||||
@@ -777,7 +832,7 @@
|
||||
<Required>N</Required>
|
||||
</stickiness_bytesOutRatePeriod>
|
||||
<http2Enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<default>1</default>
|
||||
<Required>N</Required>
|
||||
</http2Enabled>
|
||||
<http2Enabled_nontls type="BooleanField">
|
||||
@@ -795,6 +850,7 @@
|
||||
<http10>HTTP/1.0</http10>
|
||||
</OptionValues>
|
||||
</advertised_protocols>
|
||||
<!-- XXX: deprecated option (scheduled removal in os-haproxy 5.0) -->
|
||||
<forwardFor type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
@@ -1016,7 +1072,7 @@
|
||||
<Required>N</Required>
|
||||
</linkedMailer>
|
||||
<http2Enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<default>1</default>
|
||||
<Required>N</Required>
|
||||
</http2Enabled>
|
||||
<http2Enabled_nontls type="BooleanField">
|
||||
@@ -1034,6 +1090,27 @@
|
||||
<http10>HTTP/1.0</http10>
|
||||
</OptionValues>
|
||||
</ba_advertised_protocols>
|
||||
<forwardFor type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</forwardFor>
|
||||
<forwardedHeader type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</forwardedHeader>
|
||||
<forwardedHeaderParameters type="OptionField">
|
||||
<Required>N</Required>
|
||||
<Sorted>Y</Sorted>
|
||||
<Multiple>Y</Multiple>
|
||||
<OptionValues>
|
||||
<proto>proto</proto>
|
||||
<host>host</host>
|
||||
<by>by</by>
|
||||
<by_port>by_port</by_port>
|
||||
<for>for</for>
|
||||
<for_port>for_port</for_port>
|
||||
</OptionValues>
|
||||
</forwardedHeaderParameters>
|
||||
<persistence type="OptionField">
|
||||
<Required>N</Required>
|
||||
<default>sticktable</default>
|
||||
@@ -3027,6 +3104,7 @@
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</syncCertsCron>
|
||||
<!-- XXX: old value, required for model migration to 4.1.0 -->
|
||||
<updateOcsp type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2023 Frank Wall
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\HAProxy\Migrations;
|
||||
|
||||
use OPNsense\Base\BaseModelMigration;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Cron\Cron;
|
||||
|
||||
class M4_1_0 extends BaseModelMigration
|
||||
{
|
||||
public function run($model)
|
||||
{
|
||||
// Get old OCSP config item and map to new value
|
||||
$old_ocsp = (string)$model->general->storeOcsp;
|
||||
$model->general->tuning->ocspUpdateEnabled = $old_ocsp;
|
||||
|
||||
// Remove obsolete OCSP cron job
|
||||
if ((string)$model->maintenance->cronjobs->updateOcspCron != "") {
|
||||
$cron_uuid = (string)$model->maintenance->cronjobs->updateOcspCron;
|
||||
$model->maintenance->cronjobs->updateOcspCron = "";
|
||||
|
||||
// Delete the cronjob item
|
||||
$mdlCron = new Cron();
|
||||
if ($mdlCron->jobs->job->del($cron_uuid)) {
|
||||
$mdlCron->serializeToConfig();
|
||||
$model->serializeToConfig($validateFullModel = false, $disable_validation = true);
|
||||
Config::getInstance()->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,7 +717,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<li>{{ lang._('Lastly, enable HAProxy using the %sService%s settings page.') | format('<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._('Please be aware that you need to %smanually%s add the required firewall rules for all configured services.') | format('<b>', '</b>') }}</p>
|
||||
<p>{{ lang._('Further information is available in the %sofficial HAProxy documentation%s. Be sure to report bugs and request features on our %sGitHub issue page%s. Code contributions are also very welcome!') | format('<a href="http://docs.haproxy.org/2.6/configuration.html" target="_blank">', '</a>', '<a href="https://github.com/opnsense/plugins/issues/" target="_blank">', '</a>') }}</p>
|
||||
<p>{{ lang._('Further information is available in the %sofficial HAProxy documentation%s. Be sure to report bugs and request features on our %sGitHub issue page%s. Code contributions are also very welcome!') | format('<a href="http://docs.haproxy.org/2.8/configuration.html" target="_blank">', '</a>', '<a href="https://github.com/opnsense/plugins/issues/" target="_blank">', '</a>') }}</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -759,7 +759,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<li>{{ lang._('%sConditions:%s HAProxy is capable of extracting data from requests, responses and other connection data and match it against predefined patterns. Use these powerful patterns to compose a condition that may be used in multiple Rules.') | format('<b>', '</b>') }}</li>
|
||||
<li>{{ lang._('%sRules:%s Perform a large set of actions if one or more %sConditions%s match. These Rules may be used in %sBackend Pools%s as well as %sPublic Services%s.') | format('<b>', '</b>', '<b>', '</b>', '<b>', '</b>', '<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._("For more information on HAProxy's %sACL feature%s see the %sofficial documentation%s.") | format('<b>', '</b>', '<a href="http://docs.haproxy.org/2.6/configuration.html#7" target="_blank">', '</a>') }}</p>
|
||||
<p>{{ lang._("For more information on HAProxy's %sACL feature%s see the %sofficial documentation%s.") | format('<b>', '</b>', '<a href="http://docs.haproxy.org/2.8/configuration.html#7" target="_blank">', '</a>') }}</p>
|
||||
<p>{{ lang._('Note that it is possible to directly add options to the HAProxy configuration by using the "option pass-through", a setting that is available for several configuration items. It allows you to implement configurations that are currently not officially supported by this plugin. It is strongly discouraged to rely on this feature. Please report missing features on our GitHub page!') | format('<b>', '</b>') }}</p>
|
||||
<br/>
|
||||
</div>
|
||||
@@ -774,7 +774,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<li>{{ lang._('%sGroup:%s A optional list containing one or more users. Groups usually make it easier to manage permissions for a large number of users') | format('<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._('Note that users and groups must be selected from the Backend Pool or Public Service configuration in order to be used for authentication. In addition to this users and groups may also be used in Rules/Conditions.') }}</p>
|
||||
<p>{{ lang._("For more information on HAProxy's %suser/group management%s see the %sofficial documentation%s.") | format('<b>', '</b>', '<a href="http://docs.haproxy.org/2.6/configuration.html#3.4" target="_blank">', '</a>') }}</p>
|
||||
<p>{{ lang._("For more information on HAProxy's %suser/group management%s see the %sofficial documentation%s.") | format('<b>', '</b>', '<a href="http://docs.haproxy.org/2.8/configuration.html#3.4" target="_blank">', '</a>') }}</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -792,7 +792,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<li>{{ lang._("%sCache:%s HAProxy's cache which was designed to perform cache on small objects (favicon, css, etc.). This is a minimalist low-maintenance cache which runs in RAM.") | format('<b>', '</b>', '<b>', '</b>') }}</li>
|
||||
<li>{{ lang._("%sPeers:%s Configure a communication channel between two HAProxy instances. This will propagate entries of any data-types in stick-tables between these HAProxy instances over TCP connections in a multi-master fashion. Useful when aiming for a seamless failover in a HA setup.") | format('<b>', '</b>', '<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._("For more details visit HAProxy's official documentation regarding the %sStatistics%s, %sCache%s and %sPeers%s features.") | format('<a href="http://docs.haproxy.org/2.6/configuration.html#stats%20enable" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.6/configuration.html#10" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.6/configuration.html#3.5" target="_blank">', '</a>') }}</p>
|
||||
<p>{{ lang._("For more details visit HAProxy's official documentation regarding the %sStatistics%s, %sCache%s and %sPeers%s features.") | format('<a href="http://docs.haproxy.org/2.8/configuration.html#stats%20enable" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.8/configuration.html#10" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.8/configuration.html#3.5" target="_blank">', '</a>') }}</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -810,7 +810,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<li>{{ lang._("%sResolvers:%s This feature allows in-depth configuration of how HAProxy handles name resolution and interacts with name resolvers (DNS). Each resolver configuration can be used in %sBackend Pools%s to apply individual name resolution configurations.") | format('<b>', '</b>', '<b>', '</b>') }}</li>
|
||||
<li>{{ lang._("%sE-Mail Alerts:%s It is possible to send email alerts when the state of servers changes. Each configuration can be used in %sBackend Pools%s to send e-mail alerts to the configured recipient.") | format('<b>', '</b>', '<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features. More information on HAProxy's CPU Affinity is also available %shere%s, %shere%s and %shere%s. A detailed explanation of the resolvers feature can be found %shere%s.") | format('<a href="http://docs.haproxy.org/2.6/configuration.html#4-errorfile" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.6/configuration.html#lua-load" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.6/configuration.html#map" target="_blank">', '</a>' ,'<a href="http://docs.haproxy.org/2.6/configuration.html#cpu-map" target="_blank">', '</a>' ,'<a href="http://docs.haproxy.org/2.6/configuration.html#bind-process" target="_blank">', '</a>' ,'<a href="http://docs.haproxy.org/2.6/configuration.html#process" target="_blank">', '</a>','<a href="http://docs.haproxy.org/2.6/configuration.html#5.3.2" target="_blank">', '</a>') }}</p>
|
||||
<p>{{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features. More information on HAProxy's CPU Affinity is also available %shere%s, %shere%s and %shere%s. A detailed explanation of the resolvers feature can be found %shere%s.") | format('<a href="http://docs.haproxy.org/2.8/configuration.html#4-errorfile" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.8/configuration.html#lua-load" target="_blank">', '</a>', '<a href="http://docs.haproxy.org/2.8/configuration.html#map" target="_blank">', '</a>' ,'<a href="http://docs.haproxy.org/2.8/configuration.html#cpu-map" target="_blank">', '</a>' ,'<a href="http://docs.haproxy.org/2.8/configuration.html#bind-process" target="_blank">', '</a>' ,'<a href="http://docs.haproxy.org/2.8/configuration.html#process" target="_blank">', '</a>','<a href="http://docs.haproxy.org/2.8/configuration.html#5.3.2" target="_blank">', '</a>') }}</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -95,7 +95,12 @@ foreach ($configNodes as $key => $value) {
|
||||
file_put_contents($output_pem_filename, $pem_content);
|
||||
chmod($output_pem_filename, 0600);
|
||||
echo "exported $type to " . $output_pem_filename . "\n";
|
||||
$crtlist[] = $output_pem_filename;
|
||||
// Check if automatic OCSP updates are enabled.
|
||||
if (isset($configObj->OPNsense->HAProxy->general->tuning->ocspUpdateEnabled) and ($configObj->OPNsense->HAProxy->general->tuning->ocspUpdateEnabled == '1')) {
|
||||
$crtlist[] = $output_pem_filename . " ocsp-update on";
|
||||
} else {
|
||||
$crtlist[] = $output_pem_filename;
|
||||
}
|
||||
} else {
|
||||
// In contrast to certificates, CA/CRL content needs to be put in a single file.
|
||||
// A list of individual files is not supported by HAproxy.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
"""haproxy lib for socket commands.
|
||||
Based on: https://github.com/neurogeek/haproxyctl"""
|
||||
__version__ = "1.0"
|
||||
@@ -1,335 +0,0 @@
|
||||
"""cmds.py - Implementations of the different HAProxy commands"""
|
||||
import re
|
||||
import csv
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
from io import StringIO
|
||||
|
||||
class Cmd():
|
||||
"""Cmd - Command base class"""
|
||||
req_args = []
|
||||
args = {}
|
||||
cmdTxt = ""
|
||||
helpTxt = ""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Argument to the command are given in kwargs only. We ignore *args."""
|
||||
self.args = kwargs
|
||||
valid_kwargs = [k for (k, v) in kwargs.items() if v is not None]
|
||||
|
||||
if not all([a in valid_kwargs for a in self.req_args]):
|
||||
raise Exception(f"Wrong number of arguments. Required arguments are: {self.WhatArgs()}")
|
||||
|
||||
def WhatArgs(self):
|
||||
"""Returns a formatted string of arguments to this command."""
|
||||
return ",".join(self.req_args)
|
||||
|
||||
@classmethod
|
||||
def getHelp(cls):
|
||||
"""Get formatted help string for this command."""
|
||||
txtArgs = ",".join(cls.req_args)
|
||||
|
||||
if not txtArgs:
|
||||
txtArgs = "None"
|
||||
return " ".join((cls.helpTxt, "Arguments: %s" % txtArgs))
|
||||
|
||||
def getCmd(self):
|
||||
"""Gets the command line for this command.
|
||||
The default behavior is to apply the args dict to cmdTxt
|
||||
"""
|
||||
return self.cmdTxt % self.args
|
||||
|
||||
def getBootstrapOutput(self, resObj):
|
||||
""" Returns results gathered from HAProxy as jquery bootstrap output """
|
||||
args = {
|
||||
"rows": resObj,
|
||||
"page": int(self.args['page']) if self.args['page'] != None else 1,
|
||||
"page_rows": int(self.args['page_rows']) if self.args['page_rows'] != None else len(rows),
|
||||
"search": self.args['search'],
|
||||
"sort_col": self.args['sort_col'] if self.args['sort_col'] else 'id',
|
||||
"sort_dir": self.args['sort_dir'],
|
||||
}
|
||||
rows = args['rows']
|
||||
# search
|
||||
if args['search']:
|
||||
filtered_rows = []
|
||||
for row in rows:
|
||||
def inner(row):
|
||||
for k, v in row.items():
|
||||
if args['search'] in v:
|
||||
return row
|
||||
return None
|
||||
|
||||
match = inner(row)
|
||||
if match:
|
||||
filtered_rows.append(match)
|
||||
rows = filtered_rows
|
||||
|
||||
# sort
|
||||
rows.sort(key=lambda k: k[args['sort_col']], reverse=True if args['sort_dir'] == 'desc' else False)
|
||||
|
||||
# pager
|
||||
total = len(rows)
|
||||
pages = [rows[i:i + args['page_rows']] for i in range(0, total, args['page_rows'])]
|
||||
if pages and (args['page'] > len(pages) or args['page'] < 1):
|
||||
raise KeyError(f"Current page {args['page']} does not exist. Available pages: {len(pages)}")
|
||||
page = pages[args['page'] - 1] if pages else []
|
||||
|
||||
return json.dumps({
|
||||
"rows": page,
|
||||
"total": total,
|
||||
"rowCount": args['page_rows'],
|
||||
"current": args['page']
|
||||
})
|
||||
|
||||
def getJsonOutput(self, resObj):
|
||||
"""Returns results gathered from HAProxy as json"""
|
||||
return json.dumps(resObj)
|
||||
|
||||
def getResult(self, res):
|
||||
"""Returns raw results gathered from HAProxy"""
|
||||
if res == '\n':
|
||||
res = None
|
||||
|
||||
if self.args['output'] == 'json':
|
||||
return self.getJsonOutput(self.getResultObj(res))
|
||||
|
||||
if self.args['output'] == 'bootstrap':
|
||||
return self.getBootstrapOutput(self.getResultObj(res))
|
||||
|
||||
return res
|
||||
|
||||
def getResultObj(self, res):
|
||||
"""Returns refined output from HAProxy, packed inside a Python obj i.e. a dict()"""
|
||||
return res
|
||||
|
||||
class setServerAgent(Cmd):
|
||||
cmdTxt = "set server %(backend)s/%(server)s agent %(value)s\r\n"
|
||||
req_args = ['backend', 'server', 'value']
|
||||
helpTxt = "Force a server's agent to a new state."
|
||||
|
||||
class setServerHealth(Cmd):
|
||||
cmdTxt = "set server %(backend)s/%(server)s health %(value)s\r\n"
|
||||
req_args = ['backend', 'server', 'value']
|
||||
helpTxt = "Force a server's health to a new state."
|
||||
|
||||
class setServerState(Cmd):
|
||||
cmdTxt = "set server %(backend)s/%(server)s state %(value)s\r\n"
|
||||
req_args = ['backend', 'server', 'value']
|
||||
helpTxt = "Force a server's administrative state to a new state."
|
||||
|
||||
class setServerWeight(Cmd):
|
||||
cmdTxt = "set server %(backend)s/%(server)s weight %(value)s\r\n"
|
||||
req_args = ['backend', 'server', 'value']
|
||||
helpTxt = "Force a server's weight to a new state."
|
||||
|
||||
class showSslCrtLists(Cmd):
|
||||
cmdTxt = "show ssl crt-list\r\n"
|
||||
helpTxt = "Show the list of crt-lists."
|
||||
|
||||
def getResultObj(self, res):
|
||||
result = { "crt_lists": []}
|
||||
for line in res.split("\n"):
|
||||
if line.startswith('/'):
|
||||
result["crt_lists"].append(line)
|
||||
return result
|
||||
|
||||
class showSslCrtList(Cmd):
|
||||
cmdTxt = "show ssl crt-list -n %(crt_list)s\r\n"
|
||||
req_args = ['crt_list']
|
||||
helpTxt = "Show the the content of a crt-list."
|
||||
|
||||
def getResultObj(self, res):
|
||||
result = {}
|
||||
list_id = None
|
||||
for line in res.split("\n"):
|
||||
if line.startswith('# '):
|
||||
list_id = line.split("# ")[1]
|
||||
result["certs"] = []
|
||||
|
||||
if list_id and line.startswith('/'):
|
||||
result["certs"].append(line)
|
||||
|
||||
if result:
|
||||
return result
|
||||
|
||||
return {"error": res.strip()}
|
||||
|
||||
class showSslCerts(Cmd):
|
||||
cmdTxt = "show ssl cert\r\n"
|
||||
helpTxt = "Display the SSL certificates used in memory."
|
||||
|
||||
def getResultObj(self, res):
|
||||
result = {
|
||||
"transaction": [],
|
||||
"filename": []
|
||||
}
|
||||
for line in res.split("\n"):
|
||||
if line.startswith('*'):
|
||||
result['transaction'].append(line)
|
||||
elif line.startswith('/'):
|
||||
result['filename'].append(line)
|
||||
return result
|
||||
|
||||
class showSslCert(Cmd):
|
||||
cmdTxt = "show ssl cert %(certfile)s\r\n"
|
||||
req_args = ['certfile']
|
||||
helpTxt = "Display the details of a SSL certificate used in memory."
|
||||
|
||||
def getResultObj(self, res):
|
||||
result = {}
|
||||
cert_id = None
|
||||
for line in res.split("\n"):
|
||||
if line:
|
||||
key = line.split(":")[0]
|
||||
val = line.split(":")[1].strip()
|
||||
|
||||
if key == 'Filename':
|
||||
cert_id = val
|
||||
|
||||
if cert_id:
|
||||
result[key] = val
|
||||
|
||||
if result:
|
||||
return result
|
||||
|
||||
return {"error": res.strip()}
|
||||
|
||||
class addToSslCrtList(Cmd):
|
||||
cmdTxt = "add ssl crt-list %(crt_list)s %(certfile)s\r\n"
|
||||
req_args = ['crt_list', 'certfile']
|
||||
helpTxt = "Add a ssl cert to a crt-list."
|
||||
|
||||
class delFromSslCrtList(Cmd):
|
||||
cmdTxt = "del ssl crt-list %(crt_list)s %(certfile)s\r\n"
|
||||
req_args = ['crt_list', 'certfile']
|
||||
helpTxt = "Delete a ssl cert from a crt-list."
|
||||
|
||||
class newSslCrt(Cmd):
|
||||
"""" Create an empty slot for the certificate in HAProxy’s memory """
|
||||
cmdTxt = "new ssl cert %(certfile)s\r\n"
|
||||
req_args = ['certfile']
|
||||
helpTxt = "Create a new certificate file to be used in a crt-list or a directory."
|
||||
|
||||
class updateSslCrt(Cmd):
|
||||
"""" Begin a transaction to upload the certificate into a slot in HAProxy’s memory """
|
||||
cmdTxt = "set ssl cert %(certfile)s <<\n%(payload)s\r\n"
|
||||
req_args = ['certfile', 'payload']
|
||||
helpTxt = "Replace a certificate file."
|
||||
|
||||
class delSslCrt(Cmd):
|
||||
"""" Begin a transaction to remove the certificate from a slot in HAProxy’s memory """
|
||||
cmdTxt = "del ssl cert %(certfile)s\r\n"
|
||||
req_args = ['certfile']
|
||||
helpTxt = "Delete delete an unused certificate file."
|
||||
|
||||
class commitSslCrt(Cmd):
|
||||
""" Commit the transaction so HAProxy detects the change. """
|
||||
cmdTxt = "commit ssl cert %(certfile)s\r\n"
|
||||
req_args = ['certfile']
|
||||
helpTxt = "Commit a certificate file."
|
||||
|
||||
class abortSslCrt(Cmd):
|
||||
cmdTxt = "abort ssl cert %(certfile)s\r\n"
|
||||
req_args = ['certfile']
|
||||
helpTxt = "Abort a transaction for a certificate file."
|
||||
|
||||
class showFBEnds(Cmd):
|
||||
"""Base class for getting a listing Frontends and Backends"""
|
||||
switch = ""
|
||||
cmdTxt = "show stat\r\n"
|
||||
|
||||
def getResult(self, res):
|
||||
return "\n".join(self._getResult(res))
|
||||
|
||||
def getResultObj(self, res):
|
||||
return self._getResult(res)
|
||||
|
||||
def _getResult(self, res):
|
||||
"""Show Frontend/Backends. To do this, we extract info from
|
||||
the stat command and filter out by a specific
|
||||
switch (FRONTEND/BACKEND)"""
|
||||
|
||||
if not self.switch:
|
||||
raise Exception("No action specified")
|
||||
|
||||
result = []
|
||||
lines = res.split('\n')
|
||||
cl = re.compile("^[^,].+," + self.switch.upper() + ",.*$")
|
||||
|
||||
for e in lines:
|
||||
me = re.match(cl, e)
|
||||
if me:
|
||||
print(e)
|
||||
result.append(e.split(",")[0])
|
||||
return result
|
||||
|
||||
class showFrontends(showFBEnds):
|
||||
"""Show frontends command."""
|
||||
switch = "frontend"
|
||||
helpTxt = "List all Frontends."
|
||||
|
||||
class showBackends(showFBEnds):
|
||||
"""Show backends command."""
|
||||
switch = "backend"
|
||||
helpTxt = "List all Backends."
|
||||
|
||||
class showInfo(Cmd):
|
||||
"""Show info HAProxy command"""
|
||||
cmdTxt = "show info\r\n"
|
||||
helpTxt = "Show info on HAProxy instance."
|
||||
|
||||
def getResultObj(self, res):
|
||||
resDict = {}
|
||||
for line in res.split('\n'):
|
||||
k, v = line.split(':')
|
||||
resDict[k] = v
|
||||
|
||||
return resDict
|
||||
|
||||
class showSessions(Cmd):
|
||||
"""Show sess HAProxy command"""
|
||||
cmdTxt = "show sess\r\n"
|
||||
helpTxt = "Show HAProxy sessions."
|
||||
|
||||
def getResultObj(self, res):
|
||||
return res.split('\n')
|
||||
|
||||
class baseStat(Cmd):
|
||||
"""Base class for stats commands."""
|
||||
|
||||
def getDict(self, res):
|
||||
# clean response
|
||||
res = re.sub(r'^# ', '', res, re.MULTILINE)
|
||||
res = re.sub(r',\n', '\n', res, re.MULTILINE)
|
||||
res = re.sub(r',\n\n', '\n', res, re.MULTILINE)
|
||||
|
||||
csv_string = StringIO(res)
|
||||
return csv.DictReader(csv_string, delimiter=',')
|
||||
|
||||
class showServers(baseStat):
|
||||
"""Show all servers. If backend is given, show only servers for this backend. """
|
||||
cmdTxt = "show stat\r\n"
|
||||
helpTxt = "Lists all servers. Filter for servers in backend, if set."
|
||||
|
||||
def getResultObj(self, res):
|
||||
servers = []
|
||||
|
||||
reader = self.getDict(res)
|
||||
for row in reader:
|
||||
row = OrderedDict(row)
|
||||
# show only server
|
||||
if row['svname'] in ['BACKEND', 'FRONTEND']:
|
||||
continue
|
||||
|
||||
# filter server for given backend
|
||||
if self.args['backend'] and row['pxname'] != self.args['backend']:
|
||||
continue
|
||||
|
||||
# add id
|
||||
row['id'] = f"{row['pxname']}/{row['svname']}"
|
||||
row.move_to_end('id', last=False)
|
||||
servers.append(dict(row))
|
||||
|
||||
return servers
|
||||
@@ -1,83 +0,0 @@
|
||||
# pylint: disable=locally-disabled, too-few-public-methods, no-self-use, invalid-name
|
||||
"""conn.py - Connection module."""
|
||||
import re
|
||||
from socket import socket, AF_INET, AF_UNIX, SOCK_STREAM
|
||||
from haproxy import const
|
||||
|
||||
class HapError(Exception):
|
||||
"""Generic exception for haproxyctl."""
|
||||
pass
|
||||
|
||||
class HaPConn(object):
|
||||
"""HAProxy Socket object.
|
||||
This class abstract the socket interface so
|
||||
commands can be sent to HAProxy and results received and
|
||||
parse by the command objects"""
|
||||
|
||||
def __init__(self, sfile, socket_module=socket):
|
||||
"""Initializes an HAProxy and opens a connection to it
|
||||
(sfile, type) -> Path for the UNIX socket"""
|
||||
|
||||
self.sock = None
|
||||
sfile = sfile.strip()
|
||||
stype = AF_UNIX
|
||||
self.socket_module = socket_module
|
||||
|
||||
mobj = re.match(
|
||||
'(?P<proto>unix://|tcp://)(?P<addr>[^:]+):*(?P<port>[0-9]*)$', sfile)
|
||||
|
||||
if mobj:
|
||||
proto = mobj.groupdict().get('proto', None)
|
||||
addr = mobj.groupdict().get('addr', None)
|
||||
port = mobj.groupdict().get('port', '')
|
||||
|
||||
if not addr or not proto:
|
||||
raise HapError('Could not determine type of socket.')
|
||||
|
||||
if proto == const.HAP_TCP_PATH:
|
||||
if not port:
|
||||
raise HapError('When using a tcp socket, a port is needed.')
|
||||
stype = AF_INET
|
||||
sfile = (addr, int(port))
|
||||
|
||||
if proto == const.HAP_UNIX_PATH:
|
||||
stype = AF_UNIX
|
||||
sfile = addr
|
||||
|
||||
# Fallback should be sfile/AF_UNIX by default
|
||||
self.sfile = (sfile, stype)
|
||||
self.open()
|
||||
|
||||
def open(self):
|
||||
"""Opens a connection for the socket.
|
||||
This function should only be called if
|
||||
self.closed() method was called"""
|
||||
|
||||
sfile, stype = self.sfile
|
||||
self.sock = self.socket_module(stype, SOCK_STREAM)
|
||||
self.sock.connect(sfile)
|
||||
|
||||
def sendCmd(self, cmd, objectify=False):
|
||||
"""Receives a command obj and sends it to the socket. Receives the output and passes it
|
||||
through the command to parse it.
|
||||
objectify -> Return an object instead of plain text"""
|
||||
|
||||
res = ""
|
||||
try:
|
||||
self.sock.send(cmd.getCmd())
|
||||
except TypeError:
|
||||
self.sock.send(bytearray(cmd.getCmd(), 'ASCII'))
|
||||
output = self.sock.recv(const.HAP_BUFSIZE)
|
||||
|
||||
while output:
|
||||
res += output.decode('UTF-8')
|
||||
output = self.sock.recv(const.HAP_BUFSIZE)
|
||||
|
||||
if objectify:
|
||||
return cmd.getResultObj(res)
|
||||
|
||||
return cmd.getResult(res)
|
||||
|
||||
def close(self):
|
||||
"""Closes the socket"""
|
||||
self.sock.close()
|
||||
@@ -1,7 +0,0 @@
|
||||
"""const.py - Constants for haproxyctl."""
|
||||
HAP_OK = 1
|
||||
HAP_ERR = 2
|
||||
HAP_SOCK_ERR = 3
|
||||
HAP_BUFSIZE = 8192
|
||||
HAP_UNIX_PATH = 'unix://'
|
||||
HAP_TCP_PATH = 'tcp://'
|
||||
@@ -1,291 +0,0 @@
|
||||
# pylint: disable=star-args, locally-disabled, too-few-public-methods, no-self-use, invalid-name
|
||||
"""test_cmds.py - Unittests related to command implementations."""
|
||||
import sys, os, unittest
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||
from haproxy import cmds
|
||||
|
||||
|
||||
class TestCommands(unittest.TestCase):
|
||||
"""Tests all of the commands."""
|
||||
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
self.pem_cert_content = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
+VCAIWMkC36Dvg==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKgIBAAKCAgEAvsNKU59F2gpl1fzbk7hD64Q3zk1hH9Im1IsN9ppF5tqdsPPG
|
||||
n3Q8QgcKpnJ/SrtnPl4Xqp3bJyV20lJWTxuVU7ImM8g4tStQB4XojTtv8A4E7/wN
|
||||
T0beUBFI5CQ+YLzRqEYBbcXV5pxx/TyqdxYIbEopeZ4v2ZsCwDiTr7qkirxhEGow
|
||||
ITZuRFD+xwBrykvuazmFx441Z+qMcLXbMinJq++d81VnrPtCXAcSHdFqOTUhocvI
|
||||
Tv736hDfNeoW0zqwG9eW9WHCyLOCQfdmh03zXJy8eg/UxaocYdfSSVERD2pGse5K
|
||||
6oeyMkdfyC1uojZn0NU5RQS6dsiQiZPCpiN7m2nuDhFAlSAB2xq7I3TY1N15R5yL
|
||||
4kO8DcUcmkC0Du0Nch41zI+NGGjXuLhVQhxhqy7kkMXSJI8NP9KvG3oSwOe0MUNy
|
||||
jUdcywWpSExtjb6BRYLc/Sf3xVZI74EK0B0Vtzj43dAQzxGdAojzpYdH++dUOiKA
|
||||
6EAu6ldrpzOMsYyNpIsMjSfInkzzWvxm4Fla7ZDodOKQ2ahaXfDrH71a9jpNB306
|
||||
kKNBS7XdQxUByjwIYQ6PRmqGEtNxxfx3E8r/TVtcy0VGK8l97q8wv47Q3nglsjlx
|
||||
peZoR1wS5rMBUla3Vk8YVMyOLD87RLodvRVgkpeqMmz233k7kykv1bhi8bECAwEA
|
||||
AQKCAgEAswbSPXJPetahRdcdNyAKVgBq4ykJinSOTpAF1bZo/cOTlFrjwAe0+X5k
|
||||
R1tTDQ6dURG7AjtNTgrB3Za6O1m2paqeYaB5X8U7QSQx4EG0xsRRa+vPjeQDhX8D
|
||||
OmCtTdpGpLa2Zo/xM5EFBVUm4cYCt6ZOED4dyAnK5hzytUvjWfR6343Yh4LurxyY
|
||||
TqidgGgMZALDA0n54wFjNe/lu8kt5Ddns9MmDlhrqbRVEzjSiMfNPWvjHAf7IGcf
|
||||
JBkBvNDqL+b/XGCYDgUxrLkDNt44E2VhGOi8lZkVM9n5FyeGbEIgAKKTGlGpMbh8
|
||||
MoA4wPFwMrO5IIXUfN+zjfnnBkZsnAomGQYDh/hrsQPwU7MoyfO0Wzw+RzLWK8JH
|
||||
EnjR7O/Lgh+A2AdLhCLiRC5td2uuJ2yLRIRUlcQPsCsYnCCL6Ip9IwK1idmQySGw
|
||||
bG83decXNSJUv5h3qF6f3fl+JPrHnAbviBzEJ67xAf1MdHbFxwYvRFVfEHj9RZ3W
|
||||
z+cw7ofD8XVHTfXn0XipvYqI/bVsitMXI35pOt+/ZV8rjJlXopw+IV6U9/60cBkk
|
||||
BXC7ONDyH2pNwxPbRgcLm2sEK0L9qhxRzCj0iD1WyOAiFJX4ytVbJhR7pt0goiun
|
||||
i2XDh2l8hoK1lKZNS/yJ+VhnbX595mdqScmIXD8utlgK8f0bLfECggEBAORXimSK
|
||||
gzegnsBjieTtzC6MmRRxxN46vnMZ2LCeLMxhs3vM7LBcBfsQYqbt/FVFtYBRpr+d
|
||||
TGTmfPXqKuSqbtAbghxAMo/lECXzALa0nQSsz1fFhX8B7slFarsDmmCb1GmXF/kG
|
||||
ku/Uoa7jmY3htBj5rjVHjDKPZFVetU+2wbuwlU17Bj4nlSzqud4NMlu56pm3FZ/1
|
||||
BAhMxm3z6dLnOgqJzpN1QmKZHNkjLmi8fza/HQM5pP3DpQcPiyuLzywGIqHaO1qT
|
||||
OIdpZfLEvNpMV7bJ2bagv5nX3TVRWWsBkh0HCAuH30qqaVPpQvkPem1zsM3x+D5q
|
||||
+PhMIPGpbQiUyCUCggEBANXefd0ZcJymG15WJyO44eFwzgMz9ezfdB8INa+vCOiZ
|
||||
Y7FtYDgEKu4uzBxtMjO4mQO6DCkfi7JwTJFN4ag3dJEJNGmrf7Xe84IAImJQk0Of
|
||||
BojAXCFAuNf1Xl3prkvnvtzNirwQMHCUbv5wYzOqglgj2i/hjIj3/Wbt91riq5j+
|
||||
4qQT4kkw/XgCtbQ27HohKIcC/mXbHchEi7NtXrGoM1xqmu1mGH1uul3LQ6p5VwHc
|
||||
ZFiIAC0awsx9Qe9khZ5EGpZuS0tqJsREcv8ygYMvWcPJEv8aMQM7Nj4biA5rKEgo
|
||||
L+66ibpntldvbz2qntEvJ2rKzGci0RDUQHy4sW8/d50CggEBAKCZaX7ZZPzk/YL2
|
||||
/2+CSQ+cV7ZnZj2fN4Ag96UROxTsyp4SPY60yogQuDIMRGN9SfDcfNlcOvTkn5Me
|
||||
hdiafqHkFxjjlixawYbPaPsYAS/ek156UDBKHbZ2GmE6YYP9VeKGIJhHpWUFOkqV
|
||||
TdTaoB7IzVwv3E1bSQg6Om+8bHoj8n6yPmvMz0DuPpgM1BRrqLNAb/c3DwT/ari+
|
||||
ywBJHSt4TVCtMmnCouWdtvB3U0ogFLnF+2N4DUPwDMQt6yJdllIb+Y706NdkrA2Z
|
||||
jfJDq5WmVnf6i4gaqTzs4GVAj5HW9jOV9ti/DqGz+CTQXB1LN1lCDIVqG34XnTwb
|
||||
G9LjQfkCggEAZwYAt4tTtgJGWNFDlW+wT/sZIm3bX7ncpD4+Ll0w+2s4nPXFTfaj
|
||||
/4zHgkIP1t5rx2HODdlGYDS8jZpow7HDE0LN3sFgienWf5808QtDhWWLrkCLoPEe
|
||||
mdl3FeJFtgby6EaTODjMPM8kEKlvACp5E6BhsIMEQc7EYNrtNvjOFKtj3go+DWfu
|
||||
EeusQB3dGI/0h+UnS0WcOSbb7RkYbphJ9ZDdBNMTpQi7+ga6l9pP0XOrWwJYo2Gq
|
||||
yPrl0j4oJ69C54hF+RQvjIg0pT5dKSacJTYtUnn5dkcFwDFe/yMbinbhcCynwAXJ
|
||||
zqC9g4U3cCk44bbDdENPVr4IOox13NND+QKCAQEAilm2oMZoP3WGkBMTSzJl6OGd
|
||||
F8NnE95noleknNFYuThhCT6T4Z1s28VpxXV7d0DTNOtXj+TzeZq4jrwkgOSZbif0
|
||||
8ky4gRZmm0iFwvAu8ZXk1olHbhMZnCOfh0Qhd4bU2tSoWgWVIAQWEHUhDI7Q1rsX
|
||||
s4sCjYHKuNMEKdfYvxtKeiunoFqdmT65hwM9o3TfvJfm/RChb7i/nVruXQ6IhPEM
|
||||
9WYZS7hlKyqVBESJuonR15biy7Xov5ELl6A821cskZO3vTwtlBSeCDiqaeVLpKR3
|
||||
aYwf5YZo7v+N8KBSLEdLNjoKK4PfXUdczD7uOUllbd4/MRgCn4EmFvmpljGiEQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqzCCApOgAwIBAgIRAIvhKg5ZRO08VGQx8JdhT+UwDQYJKoZIhvcNAQELBQAw
|
||||
GjEYMBYGA1UEAwwPRmFrZSBMRSBSb290IFgxMB4XDTE2MDUyMzIyMDc1OVoXDTM2
|
||||
MDUyMzIyMDc1OVowIjEgMB4GA1UEAwwXRmFrZSBMRSBJbnRlcm1lZGlhdGUgWDEw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtWKySDn7rWZc5ggjz3ZB0
|
||||
8jO4xti3uzINfD5sQ7Lj7hzetUT+wQob+iXSZkhnvx+IvdbXF5/yt8aWPpUKnPym
|
||||
oLxsYiI5gQBLxNDzIec0OIaflWqAr29m7J8+NNtApEN8nZFnf3bhehZW7AxmS1m0
|
||||
ZnSsdHw0Fw+bgixPg2MQ9k9oefFeqa+7Kqdlz5bbrUYV2volxhDFtnI4Mh8BiWCN
|
||||
xDH1Hizq+GKCcHsinDZWurCqder/afJBnQs+SBSL6MVApHt+d35zjBD92fO2Je56
|
||||
dhMfzCgOKXeJ340WhW3TjD1zqLZXeaCyUNRnfOmWZV8nEhtHOFbUCU7r/KkjMZO9
|
||||
AgMBAAGjgeMwgeAwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
|
||||
HQYDVR0OBBYEFMDMA0a5WCDMXHJw8+EuyyCm9Wg6MHoGCCsGAQUFBwEBBG4wbDA0
|
||||
BggrBgEFBQcwAYYoaHR0cDovL29jc3Auc3RnLXJvb3QteDEubGV0c2VuY3J5cHQu
|
||||
b3JnLzA0BggrBgEFBQcwAoYoaHR0cDovL2NlcnQuc3RnLXJvb3QteDEubGV0c2Vu
|
||||
Y3J5cHQub3JnLzAfBgNVHSMEGDAWgBTBJnSkikSg5vogKNhcI5pFiBh54DANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEABYSu4Il+fI0MYU42OTmEj+1HqQ5DvyAeyCA6sGuZdwjF
|
||||
UGeVOv3NnLyfofuUOjEbY5irFCDtnv+0ckukUZN9lz4Q2YjWGUpW4TTu3ieTsaC9
|
||||
AFvCSgNHJyWSVtWvB5XDxsqawl1KzHzzwr132bF2rtGtazSqVqK9E07sGHMCf+zp
|
||||
DQVDVVGtqZPHwX3KqUtefE621b8RI6VCl4oD30Olf8pjuzG4JKBFRFclzLRjo/h7
|
||||
IkkfjZ8wDa7faOjVXx6n+eUQ29cIMCzr8/rNWHS9pYGGQKJiY2xmVC9h12H99Xyf
|
||||
zWE9vb5zKP3MVG6neX1hSdo7PEAb9fqRhHkqVsqUvJlIRmvXvVKTwNCP3eCjRCCI
|
||||
PTAvjV+4ni786iXwwFYNz8l3PmPLCyQXWGohnJ8iBm+5nk7O2ynaPVW0U2W+pt2w
|
||||
SVuvdDM5zGv2f9ltNWUiYZHJ1mmO97jSY/6YfdOUH66iRtQtDkHBRdkNBsMbD+Em
|
||||
2TgBldtHNSJBfB3pm9FblgOcJ0FSWcUDWJ7vO0+NTXlgrRofRT6pVywzxVo6dND0
|
||||
WzYlTWeUVsO40xJqhgUQRER9YLOLxJ0O6C8i0xFxAMKOtSdodMB3RIwt7RFQ0uyt
|
||||
n5Z5MqkYhlMI3J1tPRTp1nEt9fyGspBOO05gi148Qasp+3N+svqKomoQglNoAxU=
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
||||
|
||||
self.Resp = {
|
||||
"disable": "disable server redis-ro/redis-ro0",
|
||||
"set-server-agent": "set server redis-ro/redis-ro0 agent up",
|
||||
"set-server-health": "set server redis-ro/redis-ro0 health stopping",
|
||||
"set-server-state": "set server redis-ro/redis-ro0 state drain",
|
||||
"set-server-weight": "set server redis-ro/redis-ro0 weight 10",
|
||||
"frontends": "show stat",
|
||||
"info": "show info",
|
||||
"sessions": "show sess",
|
||||
"servers": "show stat",
|
||||
"show-ssl-crt-lists": "show ssl crt-list",
|
||||
"show-ssl-crt-list": "show ssl crt-list -n /tmp/haproxy/ssl/601a7392cc9984.99301413.certlist",
|
||||
"show-ssl-certs": "show ssl cert",
|
||||
"show-ssl-cert": "show ssl cert /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"add-to-crt-list": "add ssl crt-list /tmp/haproxy/ssl/601a7392cc9984.99301413.certlist /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"del-from-crt-list": "del ssl crt-list /tmp/haproxy/ssl/601a7392cc9984.99301413.certlist /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"new-ssl-cert": "new ssl cert /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"update-ssl-cert": "set ssl cert /tmp/haproxy/ssl/601a70e4844b0.pem <<\n%s" % self.pem_cert_content,
|
||||
"del-ssl-cert": "del ssl cert /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"commit-ssl-cert": "commit ssl cert /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"abort-ssl-cert": "abort ssl cert /tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
}
|
||||
|
||||
self.Resp = dict([(k, v + "\r\n") for k, v in self.Resp.items()])
|
||||
|
||||
def test_setServerAgent(self):
|
||||
"""Test 'set server agent' command"""
|
||||
args = {"backend": "redis-ro", "server": "redis-ro0", "value": "up"}
|
||||
cmdOutput = cmds.setServerAgent(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["set-server-agent"])
|
||||
|
||||
def test_setServerHealth(self):
|
||||
"""Test 'set server health' command"""
|
||||
args = {"backend": "redis-ro", "server": "redis-ro0", "value": "stopping"}
|
||||
cmdOutput = cmds.setServerHealth(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["set-server-health"])
|
||||
|
||||
def test_setServerState(self):
|
||||
"""Test 'set server state' command"""
|
||||
args = {"backend": "redis-ro", "server": "redis-ro0", "value": "drain"}
|
||||
cmdOutput = cmds.setServerState(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["set-server-state"])
|
||||
|
||||
def test_setServerWeight(self):
|
||||
"""Test 'set server weight' command"""
|
||||
args = {"backend": "redis-ro", "server": "redis-ro0", "value": "10"}
|
||||
cmdOutput = cmds.setServerWeight(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["set-server-weight"])
|
||||
|
||||
def test_showFrontends(self):
|
||||
"""Test 'frontends/backends' commands"""
|
||||
args = {}
|
||||
cmdOutput = cmds.showFrontends(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["frontends"])
|
||||
|
||||
def test_showInfo(self):
|
||||
"""Test 'show info' command"""
|
||||
cmdOutput = cmds.showInfo().getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["info"])
|
||||
|
||||
def test_showSessions(self):
|
||||
"""Test 'show sess' command"""
|
||||
cmdOutput = cmds.showSessions().getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["sessions"])
|
||||
|
||||
def test_showServers(self):
|
||||
"""Test 'show stat' command"""
|
||||
args = {"backend": "redis-ro"}
|
||||
cmdOutput = cmds.showServers(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["servers"])
|
||||
|
||||
def test_showSslCrtLists(self):
|
||||
"""Test 'show ssl crt-list' command"""
|
||||
cmdOutput = cmds.showSslCrtLists().getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["show-ssl-crt-lists"])
|
||||
|
||||
def test_showSslCrtList(self):
|
||||
"""Test 'show ssl crt-list <crt-list>' command"""
|
||||
args = {
|
||||
"crt_list": "/tmp/haproxy/ssl/601a7392cc9984.99301413.certlist",
|
||||
}
|
||||
cmdOutput = cmds.showSslCrtList(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["show-ssl-crt-list"])
|
||||
|
||||
def test_showSslCerts(self):
|
||||
"""Test 'show ssl cert' command"""
|
||||
cmdOutput = cmds.showSslCerts().getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["show-ssl-certs"])
|
||||
|
||||
def test_showSslCert(self):
|
||||
"""Test 'show ssl cert <certfile>' command"""
|
||||
args = {
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem"
|
||||
}
|
||||
cmdOutput = cmds.showSslCert(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["show-ssl-cert"])
|
||||
|
||||
def test_addToSslCrtList(self):
|
||||
"""Test 'add ssl crt-list <crt-list> <certfile>' command"""
|
||||
args = {
|
||||
"crt_list": "/tmp/haproxy/ssl/601a7392cc9984.99301413.certlist",
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem"
|
||||
}
|
||||
cmdOutput = cmds.addToSslCrtList(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["add-to-crt-list"])
|
||||
|
||||
def test_delFromSslCrtList(self):
|
||||
"""Test 'del ssl crt-list <crt-list> <certfile>' command"""
|
||||
args = {
|
||||
"crt_list": "/tmp/haproxy/ssl/601a7392cc9984.99301413.certlist",
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem"
|
||||
}
|
||||
cmdOutput = cmds.delFromSslCrtList(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["del-from-crt-list"])
|
||||
|
||||
def test_newSslCrt(self):
|
||||
"""Test 'new ssl cert <certfile>' command"""
|
||||
args = {
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
}
|
||||
cmdOutput = cmds.newSslCrt(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["new-ssl-cert"])
|
||||
|
||||
def test_updateSslCrt(self):
|
||||
"""Test 'set ssl cert <certfile> <payload>' command"""
|
||||
args = {
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
"payload": "%s" % self.pem_cert_content
|
||||
}
|
||||
cmdOutput = cmds.updateSslCrt(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["update-ssl-cert"])
|
||||
|
||||
def test_delSslCrt(self):
|
||||
"""Test 'del ssl cert <certfile>' command"""
|
||||
args = {
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
}
|
||||
cmdOutput = cmds.delSslCrt(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["del-ssl-cert"])
|
||||
|
||||
def test_commitSslCrt(self):
|
||||
"""Test 'commit ssl cert <certfile>' command"""
|
||||
args = {
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
}
|
||||
cmdOutput = cmds.commitSslCrt(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["commit-ssl-cert"])
|
||||
|
||||
def test_abortSslCrt(self):
|
||||
"""Test 'abort ssl cert <certfile>' command"""
|
||||
args = {
|
||||
"certfile": "/tmp/haproxy/ssl/601a70e4844b0.pem",
|
||||
}
|
||||
cmdOutput = cmds.abortSslCrt(**args).getCmd()
|
||||
self.assertEqual(cmdOutput, self.Resp["abort-ssl-cert"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user