diff --git a/deploy/tests/config/2.configmap.yaml b/deploy/tests/config/2.configmap.yaml index 45ae8e07..c17a042b 100644 --- a/deploy/tests/config/2.configmap.yaml +++ b/deploy/tests/config/2.configmap.yaml @@ -17,3 +17,4 @@ data: timeout-queue: 5s timeout-server: 50s timeout-tunnel: 1h + cr-global: haproxy-controller/global-full diff --git a/deploy/tests/e2e/crd/config/cr/global-full.yaml b/deploy/tests/e2e/crd/config/cr/global-full.yaml new file mode 100644 index 00000000..162d76d2 --- /dev/null +++ b/deploy/tests/e2e/crd/config/cr/global-full.yaml @@ -0,0 +1,346 @@ +apiVersion: ingress.v1.haproxy.org/v1 +kind: Global +metadata: + name: global-full + namespace: haproxy-controller +spec: + config: + anonkey: 0 + busy_polling: false + ca_base: "" + #chroot: "aword" + close_spread_time: 0 + cluster_secret: "" + cpu_maps: + - cpu_set: "1/1" + process: "1" + crt_base: "" + daemon: "enabled" + #default_path: # Set by Ingress Controller, Cannot change. + #path: "aword" + #type: "parent" + description: "a test globals" + device_atlas_options: + json_file: "" + log_level: "" + properties_cookie: "" + separator: "" + expose_experimental_directives: false + external_check: false + fifty_one_degrees_options: + cache_size: 0 + data_file: "" + property_name_list: "" + property_separator: "" + gid: 0 + grace: 0 + group: "root" + h1_case_adjust: + - from: "content-length" + to: "Content-length" + h1_case_adjust_file: "" + h2_workaround_bogus_websocket_clients: false + hard_stop_after: 0 + httpclient_resolvers_disabled: "enabled" + httpclient_resolvers_id: "" + httpclient_resolvers_prefer: "ipv6" + httpclient_retries: 0 + httpclient_ssl_ca_file: "" + httpclient_ssl_verify: "none" + httpclient_timeout_connect: 0 + insecure_fork_wanted: false + insecure_setuid_wanted: false + issuers_chain_path: "" + limited_quic: false + load_server_state_from_file: "none" + #localpeer: "" + log_send_hostname: + enabled: "enabled" + param: "aword" + lua_load_per_thread: "" + # lua_loads: + # - file: "aword" + lua_prepend_path: + - path: "aword" + type: "cpath" + #master-worker: false # Set by Ingress Controller, Cannot change. + max_spread_checks: 0 + maxcompcpuusage: 0 + maxcomprate: 0 + maxconn: 1007 + maxconnrate: 0 + maxpipes: 0 + maxsessrate: 0 + maxsslconn: 0 + maxsslrate: 0 + maxzlibmem: 0 + mworker_max_reloads: 0 + nbproc: 0 + nbthread: 0 + no-quic: false + node: "" + noepoll: false + noevports: false + nogetaddrinfo: false + nokqueue: false + nopoll: false + noreuseport: false + nosplice: false + numa_cpu_mapping: "enabled" + #pidfile: "" # Set by Ingress Controller, Cannot change. + pp2_never_send_local: false + prealloc-fd: false + presetenv: + - name: "test1" + value: "test1" + profiling_tasks: "auto" + quiet: false + resetenv: "" + runtime_apis: + - accept_netscaler_cip: 0 + accept_proxy: false + address: "0.0.0.0:31025" + allow_0rtt: false + alpn: "aword" + backlog: "" + ca_ignore_err: "" + ca_sign_file: "" + ca_sign_pass: "" + ca_verify_file: "" + ciphers: "" + ciphersuites: "" + client_sigalgs: "" + crl_file: "" + crt_ignore_err: "" + crt_list: "" + curves: "" + defer_accept: false + ecdhe: "" + expose_fd_listeners: false + force_sslv3: false + force_tlsv10: false + force_tlsv11: false + force_tlsv12: false + force_tlsv13: false + generate_certificates: false + gid: 0 + group: "" + id: "" + interface: "" + level: "admin" + maxconn: 10005 + mode: "" + mss: "" + name: "aword" + namespace: "" + nbconn: 0 + nice: 0 + no_alpn: false + no_ca_names: false + no_sslv3: false + no_tls_tickets: false + no_tlsv10: false + no_tlsv11: false + no_tlsv12: false + no_tlsv13: false + npn: "" + prefer_client_ciphers: false + # haproxy error: process + # 'stats socket' ''process aword' on 'bind' lines is not supported anymore, please use 'thread' instead.' + # process: "aword" # + # Deprecated + proto: "" + quic-cc-algo: "newreno" + quic-force-retry: true + # haproxy error: quic-socket + # 'stats socket' unknown keyword 'quic-socket'. Did you mean 'quic-force-retry' maybe ?" + # haproxy >= 2.9 + #quic-socket: "connection" + severity_output: "none" + sigalgs: "" + ssl: false + #ssl_cafile: "" + #ssl_certificate: "aword" + ssl_max_ver: "SSLv3" + ssl_min_ver: "TLSv1.1" + strict_sni: false + tcp_user_timeout: 0 + tfo: false + thread: "all" + tls_ticket_keys: "" + transparent: false + uid: "" + user: "" + v4v6: false + v6only: false + verify: "optional" + server_state_base: "ssb_word" + #server_state_file: "ssf_word" # no file exists + set_dumpable: false + set_var: + - expr: "int(100)" + name: "proc.test2" + set_var_fmt: + - format: "primary" + name: "proc.current_state" + setcap: "cap_net_bind_service" + setenv: + - name: "test3" + value: "test3" + spread_checks: 0 + ssl_default_bind_ciphers: "" + ssl_default_bind_ciphersuites: "" + ssl_default_bind_client_sigalgs: "" + ssl_default_bind_curves: "" + ssl_default_bind_options: "" + ssl_default_bind_sigalgs: "" + ssl_default_server_ciphers: "" + ssl_default_server_ciphersuites: "" + ssl_default_server_client_sigalgs: "" + ssl_default_server_curves: "" + ssl_default_server_options: "" + ssl_default_server_sigalgs: "" + ssl_dh_param_file: "" + # haproxy error: ssl_engines + # unknown keyword 'ssl-engine' in 'global' section" + # HAProxy Version 2.6 disabled the support for engines in the default build. + # This option is only available when HAProxy has been built with support for it. + # In case the ssl-engine is required HAProxy can be rebuild with the USE_ENGINE=1 flag. + # ssl_engines: + # - algorithms: "RSA,DSA" + # name: "rdrand" + ssl_load_extra_files: "" + ssl_mode_async: "enabled" + ssl_propquery: "" + ssl_provider: "" + ssl_provider_path: "" + ssl_server_verify: "none" + ssl_skip_self_issued_ca: false + stats_maxconn: 10008 + stats_timeout: 6000 + strict_limits: false + # thread_group_lines: + # - group: "" + # num_or_range: "" + #thread_groups: 0 + tune_options: + buffers_limit: 0 + buffers_reserve: 3 + bufsize: 0 + comp_maxlevel: 0 + disable_zero_copy_forwarding: false + # haproxy error + # unknown keyword 'tune.events.max-events-at-once' in 'global' section; did you mean 'tune.maxpollevents' maybe ?" + # haproxy >= 2.9 + #events_max_events_at_once: 10000 + fail_alloc: false + # haproxy error: fd_edge_triggered + # 'tune.fd.edge-triggered' directive is experimental, must be allowed via a global 'expose-experimental-directives'" + # experimental feature + #fd_edge_triggered: "disabled" + h2_be_initial_window_size: 0 + h2_be_max_concurrent_streams: 0 + h2_fe_initial_window_size: 0 + h2_fe_max_concurrent_streams: 0 + h2_header_table_size: 0 + h2_initial_window_size: 0 + h2_max_concurrent_streams: 0 + h2_max_frame_size: 0 + http_cookielen: 0 + http_logurilen: 0 + http_maxhdr: 100 + idle_pool_shared: "disabled" + idletimer: 0 + listener_default_shards: "by-process" + listener_multi_queue: "disabled" + lua_burst_timeout: 0 + lua_forced_yield: 0 + lua_log_loggers: "disabled" + lua_log_stderr: "disabled" + lua_maxmem: false + lua_service_timeout: 0 + lua_session_timeout: 0 + lua_task_timeout: 0 + # haproxy error: max_checks_per_thread + # unknown keyword 'tune.max-checks-per-thread' in 'global' section; did you mean 'max-spread-checks' maybe ?" + # haproxy >= 2.9 + #max_checks_per_thread: 0 + maxaccept: 0 + maxpollevents: 0 + maxrewrite: 0 + memory_hot_size: 7 + pattern_cache_size: 0 + peers_max_updates_at_once: 0 + pipesize: 0 + pool_high_fd_ratio: 0 + pool_low_fd_ratio: 0 + quic_frontend_conn_tx_buffers_limit: 7 + quic_frontend_max_idle_timeout: 0 + quic_frontend_max_streams_bidi: 8 + quic_max_frame_loss: 10 + quic_retry_threshold: 10 + quic_socket_owner: "connection" + # haproxy error: rcvbuf_backend, rcvbuf_frontend + # unknown keyword 'tune.rcvbuf.backend' in 'global' section; did you mean 'tune.rcvbuf.client' maybe ?" + # haproxy >= 2.9 + #rcvbuf_backend: 0 + rcvbuf_client: 0 + #rcvbuf_frontend: 0 + rcvbuf_server: 0 + recv_enough: 0 + runqueue_depth: 0 + sched_low_latency: "disabled" + # haproxy error: sndbuf_backend, sndbuf_frontend + # unknown keyword 'tune.sndbuf.backend' in 'global' section; + # unknown keyword 'tune.sndbuf.frontend' in 'global' section; + # haproxy >= 2.9 + #sndbuf_backend: 0 + sndbuf_client: 0 + #sndbuf_frontend: 0 + sndbuf_server: 0 + ssl_cachesize: 0 + ssl_capture_buffer_size: 0 + ssl_ctx_cache_size: 0 + ssl_default_dh_param: 0 + ssl_force_private_cache: false + ssl_keylog: "disabled" + ssl_lifetime: 0 + ssl_maxrecord: 0 + ssl_ocsp_update_max_delay: 0 + ssl_ocsp_update_min_delay: 0 + stick_counters: 0 + vars_global_max_size: 0 + vars_proc_max_size: 0 + vars_reqres_max_size: 0 + vars_sess_max_size: 0 + vars_txn_max_size: 0 + # haproxy error: zlib_memlevel, zlib_windowsize + # unknown keyword 'tune.zlib.memlevel' in 'global' section; + # unknown keyword 'tune.zlib.windowsize' in 'global' section; + # haproxy >= 2.9 + #zlib_memlevel: 1 + #zlib_windowsize: 8 + tune_ssl_default_dh_param: 0 + uid: 0 + ulimit_n: 0 + unsetenv: "" + user: "root" + wurfl_options: + cache_size: 0 + data_file: "" + information_list: "" + information_list_separator: "" + patch_file: "" + zero_warning: false + log_targets: + - address: "1.2.3.4" + facility: "mail" + format: "rfc3164" + global: false + index: 0 + length: 0 + level: "emerg" + minlevel: "debug" + nolog: false + sample_range: "" + sample_size: 0 diff --git a/deploy/tests/e2e/crd/cr_deploy_validation_test.go b/deploy/tests/e2e/crd/cr_deploy_validation_test.go index bf64310b..fd16badc 100644 --- a/deploy/tests/e2e/crd/cr_deploy_validation_test.go +++ b/deploy/tests/e2e/crd/cr_deploy_validation_test.go @@ -16,7 +16,22 @@ package crd -func (suite *CRDSuite) Test_CRD_Deploy_OK() { +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +// Adding GlobalSuite, just to be able to debug directly here and not from CRDSuite +type DeployCRDSuite struct { + CRDSuite +} + +func TestDeployCRDSuite(t *testing.T) { + suite.Run(t, new(DeployCRDSuite)) +} + +func (suite *DeployCRDSuite) Test_CRD_Deploy_OK() { suite.Run("CRs OK", func() { suite.tmplData.BackendHashTypeFunction = "sdbm" // enum ok suite.tmplData.GlobalBuffersReserve = 3 // min ok @@ -28,7 +43,7 @@ func (suite *CRDSuite) Test_CRD_Deploy_OK() { }) } -func (suite *CRDSuite) Test_CRD_Deploy_NOK() { +func (suite *DeployCRDSuite) Test_CRD_Deploy_NOK() { suite.Run("CRs Enum NOK", func() { suite.tmplData.BackendHashTypeFunction = "somethingelse" // enum NOK suite.tmplData.GlobalBuffersReserve = 3 // min ok diff --git a/deploy/tests/e2e/crd/cr_global_test.go b/deploy/tests/e2e/crd/cr_global_test.go new file mode 100644 index 00000000..1c7d83c5 --- /dev/null +++ b/deploy/tests/e2e/crd/cr_global_test.go @@ -0,0 +1,224 @@ +// Copyright 2019 HAProxy Technologies LLC +// +// 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. + +//go:build e2e_sequential + +package crd + +import ( + "fmt" + "strings" + "testing" + + parser "github.com/haproxytech/config-parser/v5" + "github.com/haproxytech/config-parser/v5/common" + "github.com/haproxytech/config-parser/v5/options" + "github.com/haproxytech/config-parser/v5/params" + "github.com/haproxytech/config-parser/v5/types" + "github.com/haproxytech/kubernetes-ingress/deploy/tests/e2e" + "github.com/stretchr/testify/suite" +) + +// Adding GlobalSuite, just to be able to debug directly here and not from CRDSuite +type GlobalSuite struct { + CRDSuite +} + +func TestGlobalSuite(t *testing.T) { + suite.Run(t, new(GlobalSuite)) +} + +func (suite *GlobalSuite) Test_CR_Global() { + suite.Run("CRs OK", func() { + initialVersion := suite.getVersion() + + manifest := "config/cr/global-full.yaml" + suite.Require().NoError(suite.test.Apply(manifest, "", nil)) + // Wait for version to be incremented + suite.Eventually(func() bool { + versionUpdated := suite.getVersion() + return versionUpdated != initialVersion + }, e2e.WaitDuration, e2e.TickDuration) + + // Get updated config and do all neede param checks + cfg, err := suite.test.GetIngressControllerFile("/etc/haproxy/haproxy.cfg") + suite.NoError(err, "Could not get Haproxy config") + reader := strings.NewReader(cfg) + p, err := parser.New(options.Reader(reader)) + suite.NoError(err, "Could not get Haproxy config parser") + suite.checkGlobalParam(p, "default-path", &types.DefaultPath{ + Type: "config", + }) + suite.checkGlobalParam(p, "cpu-map", []types.CPUMap{ + { + Process: "1", + CPUSet: "1/1", + }, + }) + suite.checkGlobalParam(p, "daemon", &types.Enabled{}) + suite.checkGlobalParam(p, "group", &types.StringC{Value: "root"}) + suite.checkGlobalParam(p, "user", &types.StringC{Value: "root"}) + suite.checkGlobalParam(p, "h1-case-adjust", []types.H1CaseAdjust{ + { + From: "content-length", + To: "Content-length", + }, + }) + suite.checkGlobalParam(p, "httpclient.resolvers.disabled", &types.StringC{Value: "on"}) + suite.checkGlobalParam(p, "httpclient.resolvers.prefer", &types.HTTPClientResolversPrefer{ + Type: "ipv6", + }) + suite.checkGlobalParam(p, "httpclient.ssl.verify", &types.HTTPClientSSLVerify{ + Type: "none", + }) + // log-server-state-from-file + // CN: models/global.go: LoadServerStateFromFile not implemented + // not serialized in SerializeGlobalSection + // # https://gitlab.int.haproxy.com/haproxy-controller/gophers/-/issues/1488 + // Check to do when fix is done in client-native + suite.checkGlobalParam(p, "log-send-hostname", &types.StringC{Value: "aword"}) + suite.checkGlobalParam(p, "lua-prepend-path", []types.LuaPrependPath{ + { + Path: "aword", + Type: "cpath", + }, + }) + suite.checkGlobalParam(p, "maxconn", &types.Int64C{Value: 1007}) + suite.checkGlobalParam(p, "numa-cpu-mapping", &types.NumaCPUMapping{ + NoOption: false, + }) + suite.checkGlobalParam(p, "presetenv", []types.StringKeyValueC{ + { + Key: "test1", + Value: "test1", + }, + }) + suite.checkGlobalParam(p, "profiling.tasks", &types.StringC{Value: "auto"}) + suite.checkGlobalParam(p, "stats socket", []types.Socket{ + { + Path: "/var/run/haproxy-runtime-api.sock", + Params: []params.BindOption{ + ¶ms.BindOptionDoubleWord{ + Name: "expose-fd", + Value: "listeners", + }, + ¶ms.BindOptionValue{ + Name: "level", + Value: "admin", + }, + }, + }, + { + Path: "0.0.0.0:31025", + Params: []params.BindOption{ + ¶ms.BindOptionValue{ + Name: "name", + Value: "aword", + }, + ¶ms.BindOptionValue{ + Name: "tcp-ut", + Value: "0", + }, + ¶ms.BindOptionValue{ + Name: "verify", + Value: "optional", + }, + ¶ms.BindOptionValue{ + Name: "alpn", + Value: "aword", + }, + ¶ms.BindOptionValue{ + Name: "level", + Value: "admin", + }, + ¶ms.BindOptionValue{ + Name: "severity-output", + Value: "none", + }, + ¶ms.BindOptionValue{ + Name: "maxconn", + Value: "10005", + }, + ¶ms.BindOptionValue{ + Name: "ssl-max-ver", + Value: "SSLv3", + }, + ¶ms.BindOptionValue{ + Name: "ssl-min-ver", + Value: "TLSv1.1", + }, + ¶ms.BindOptionValue{ + Name: "thread", + Value: "all", + }, + ¶ms.BindOptionValue{ + Name: "quic-cc-algo", + Value: "newreno", + }, + ¶ms.BindOptionWord{ + Name: "quic-force-retry", + }, + }, + }, + }) + suite.checkGlobalParam(p, "set-var", []types.SetVar{ + { + Expr: common.Expression{Expr: []string{"int(100)"}}, + Name: "proc.test2", + }, + }) + suite.checkGlobalParam(p, "set-var-fmt", []types.SetVarFmt{ + { + Format: "primary", + Name: "proc.current_state", + }, + }) + suite.checkGlobalParam(p, "setcap", &types.StringC{Value: "cap_net_bind_service"}) + suite.checkGlobalParam(p, "ssl-mode-async", &types.SslModeAsync{}) + suite.checkGlobalParam(p, "ssl-server-verify", &types.StringC{Value: "none"}) + suite.checkGlobalParam(p, "stats maxconn", &types.Int64C{Value: 10008}) + suite.checkGlobalParam(p, "stats timeout", &types.StringC{Value: "6000"}) + + suite.checkGlobalParam(p, "tune.buffers.reserve", &types.Int64C{Value: 3}) + suite.checkGlobalParam(p, "tune.http.maxhdr", &types.Int64C{Value: 100}) + suite.checkGlobalParam(p, "tune.listener.default-shards", &types.StringC{Value: "by-process"}) + suite.checkGlobalParam(p, "tune.quic.frontend.conn-tx-buffers.limit", &types.Int64C{Value: 7}) + suite.checkGlobalParam(p, "tune.quic.frontend.max-streams-bidi", &types.Int64C{Value: 8}) + suite.checkGlobalParam(p, "tune.quic.max-frame-loss", &types.Int64C{Value: 10}) + suite.checkGlobalParam(p, "tune.quic.retry-threshold", &types.Int64C{Value: 10}) + suite.checkGlobalParam(p, "tune.quic.socket-owner", &types.QuicSocketOwner{Owner: "connection"}) + + suite.checkLogTargetParam(p, "log", types.Log{ + Address: "1.2.3.4", + Facility: "mail", + Format: "rfc3164", + Level: "emerg", + MinLevel: "debug", + }) + + suite.Require().NoError(suite.test.Delete(manifest)) + }) +} + +func (suite *GlobalSuite) checkGlobalParam(p parser.Parser, param string, value common.ParserData) { + v, err := p.Get(parser.Global, parser.GlobalSectionName, param) + suite.NoError(err, "Could not get Haproxy config parser Global param %s", param) + suite.Equal(value, v, fmt.Sprintf("Global param %s should be equal to %v but is %v", param, value, v)) +} + +func (suite *GlobalSuite) checkLogTargetParam(p parser.Parser, param string, value common.ParserData) { + v, err := p.GetOne(parser.Global, parser.GlobalSectionName, param, 0) + suite.NoError(err, "Could not get Haproxy config parser Global param %s", param) + suite.Equal(value, v, fmt.Sprintf("Global param %s should be equal to %v but is %v", param, value, v)) +} diff --git a/deploy/tests/e2e/crd/suite_test.go b/deploy/tests/e2e/crd/suite_test.go index e5b800e9..e3c7669a 100644 --- a/deploy/tests/e2e/crd/suite_test.go +++ b/deploy/tests/e2e/crd/suite_test.go @@ -12,15 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build e2e_parallel +//go:build e2e_parallel || e2e_sequential package crd import ( - "testing" + "strings" "github.com/stretchr/testify/suite" + parser "github.com/haproxytech/config-parser/v5" + "github.com/haproxytech/config-parser/v5/options" + "github.com/haproxytech/config-parser/v5/types" "github.com/haproxytech/kubernetes-ingress/deploy/tests/e2e" ) @@ -67,6 +70,15 @@ func (suite *CRDSuite) TearDownSuite() { suite.test.TearDown() } -func TestCRDSuite(t *testing.T) { - suite.Run(t, new(CRDSuite)) +func (suite *CRDSuite) getVersion() int64 { + cfg, err := suite.test.GetIngressControllerFile("/etc/haproxy/haproxy.cfg") + suite.NoError(err, "Could not get Haproxy config") + reader := strings.NewReader(cfg) + p, err := parser.New(options.Reader(reader)) + suite.NoError(err, "Could not get Haproxy config parser") + + data, _ := p.Get(parser.Comments, parser.CommentsSectionName, "# _version", false) + + ver, _ := data.(*types.ConfigVersion) + return ver.Value } diff --git a/deploy/tests/e2e/dump.go b/deploy/tests/e2e/dump.go new file mode 100644 index 00000000..5d276cb5 --- /dev/null +++ b/deploy/tests/e2e/dump.go @@ -0,0 +1,34 @@ +// Copyright 2019 HAProxy Technologies LLC +// +// 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. + +package e2e + +import "strings" + +func (t Test) GetIngressControllerFile(path string) (string, error) { + po, err := t.getIngressControllerPod() + if err != nil { + return "", err + } + out, errExec := t.execute("", "kubectl", "exec", "-i", "-n", "haproxy-controller", + po, "--", "cat", path) + + return out, errExec +} + +func (t Test) getIngressControllerPod() (string, error) { + out, errExec := t.execute("", "kubectl", "get", "pods", "-n", "haproxy-controller", + "-l", "run=haproxy-ingress", "-o", "name", "--field-selector=status.phase==Running", "-l", "run=haproxy-ingress") + return strings.TrimSuffix(out, "\n"), errExec +} diff --git a/deploy/tests/e2e/utils.go b/deploy/tests/e2e/utils.go index 8eb55c9c..1d48a2eb 100644 --- a/deploy/tests/e2e/utils.go +++ b/deploy/tests/e2e/utils.go @@ -145,7 +145,7 @@ func (t *Test) GetK8sVersion() (major, minor int, err error) { return major, minor, nil } -func (t *Test) execute(entry, command string, args ...string) (string, error) { +func (t *Test) execute(entry, command string, args ...string) (string, error) { //nolint: unparam cmd := exec.Command(command, args...) var b bytes.Buffer b.WriteString(entry) diff --git a/documentation/custom-resources.md b/documentation/custom-resources.md index 22d8f688..21491cdb 100644 --- a/documentation/custom-resources.md +++ b/documentation/custom-resources.md @@ -52,6 +52,25 @@ data: cr-global: haproxy-controller/myglobal ``` +### Global CRD: Note of versions compatibility between CRD and haproxy + +The `ingress.v1.haproxy.org/Global` CRD `version v1` is using client-native v5 that contains `haproxy 2.9`` keywords. + +An annototation in the CRD is available to specify the version of client-native used: `haproxy.org/client-native` + +Ingress Controller is deployed with `haproxy 2.8`. +Note that the following fields of the CRD are `haproxy 2.9` keywords and cannot be used with this version of Ingress Controller, even if defined the `Globals` CRD: +- `runtime_api.quic-socket` +- `tune_options.events_max_events_at_once` +- `tune_options.max_checks_per_thread` +- `tune_options.rcvbuf_backend` +- `tune_options.rcvbuf_frontend` +- `tune_options.sndbuf_backend` +- `tune_options.sndbuf_frontend` +- `tune_options.zlib_memlevel` +- `tune_options.zlib_windowsize` + + ### Defaults The Defaults resource is used to configure the HAProxy defaults section by referencing the resouce via the `cr-defaults` annotation in the Ingress Controller ConfigMap.