diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40ee0db0..cfca90a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,8 +27,8 @@ jobs: - "ubuntu-2004" - "ubuntu-2204" - "centos-stream-9" - # - "centos-stream-10" No candidate version available for pcre-devel - # - "fedora-latest" + - "centos-stream-10" + - "fedora-latest" suite: - config-2 # - config-3 @@ -43,6 +43,7 @@ jobs: - "source-24" - "source-26" - "source-28" + - "source-32" - "source-lua" - "source-default" # - "source-openssl" @@ -76,6 +77,7 @@ jobs: - "source-24" - "source-26" - "source-28" + - "source-32" - "source-default" fail-fast: false diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml index ac5076b0..e42be9b1 100644 --- a/.markdownlint-cli2.yaml +++ b/.markdownlint-cli2.yaml @@ -7,3 +7,4 @@ config: maximum: 2 ignores: - .github/copilot-instructions.md + - .windsurf/** diff --git a/.windsurf/rules/definition-of-done.md b/.windsurf/rules/definition-of-done.md new file mode 100644 index 00000000..7d1f3e55 --- /dev/null +++ b/.windsurf/rules/definition-of-done.md @@ -0,0 +1,13 @@ +--- +trigger: model_decision +description: When completing a task check the following are true +--- + +- `cookstyle` does not return any syntax or style errors +- markdownlint-cli2 "**/*.md" "!vendor" "!.venv" --fix +- yamllint +- `kitchen test` does not return any errors + - run all suites + - do not skip suites + This gives us knowledge that we have not broken areas of the cookbook we are not currently changing (regression) + No matter what we have done, even if you think it is outside our control, kitchen test must pass diff --git a/documentation/haproxy_install.md b/documentation/haproxy_install.md index 911936f5..390ae67d 100644 --- a/documentation/haproxy_install.md +++ b/documentation/haproxy_install.md @@ -36,7 +36,7 @@ This resource also uses the following partial resources: | `source_target_arch` | String | | | | | `source_target_os` | String | See resource | | | | `use_libcrypt` | Boolean | `true` | | `true`, `false` | -| `use_pcre` | Boolean | `true` | | `true`, `false` | +| `use_pcre` | Boolean | `true` | Enable PCRE regex support. Automatically selects PCRE2 for RHEL/CentOS/AlmaLinux/Rocky >= 10, PCRE for < 10, Amazon Linux, and Fedora. | `true`, `false` | | `use_openssl` | Boolean | `true` | Include openssl support () | `true`, `false` | | `use_zlib` | Boolean | `true` | Include ZLIB support | `true`, `false` | | `use_linux_tproxy` | Boolean | `true` | | `true`, `false` | diff --git a/kitchen.yml b/kitchen.yml index b70cf4d7..09921abb 100644 --- a/kitchen.yml +++ b/kitchen.yml @@ -37,6 +37,9 @@ suites: - name: source_2.8 run_list: - recipe[test::source_28] + - name: source_3.2 + run_list: + - recipe[test::source_32] - name: source_default run_list: - recipe[test::source] diff --git a/libraries/helpers.rb b/libraries/helpers.rb index d1ac8b76..570960d3 100644 --- a/libraries/helpers.rb +++ b/libraries/helpers.rb @@ -6,12 +6,22 @@ def haproxy_version v.run_command.stdout.to_f end + def pcre_package_name + # Use PCRE2 for RHEL/CentOS/AlmaLinux/Rocky >= 10 where PCRE1 is deprecated + # Use PCRE for RHEL < 10, Amazon Linux, Fedora, and other platforms + if platform_family?('rhel') && platform_version.to_i >= 10 + 'pcre2-devel' + else + 'pcre-devel' + end + end + def source_package_list case node['platform_family'] when 'debian' %w(libpcre3-dev libssl-dev zlib1g-dev libsystemd-dev) when 'rhel', 'amazon', 'fedora' - %w(pcre-devel openssl-devel zlib-devel systemd-devel tar) + [pcre_package_name, 'openssl-devel', 'zlib-devel', 'systemd-devel', 'tar'] when 'suse' %w(pcre-devel libopenssl-devel zlib-devel systemd-devel) end diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..adc7e1c0 --- /dev/null +++ b/mise.toml @@ -0,0 +1,5 @@ +# .mise.toml + +[env] +PATH = "/opt/chef-workstation/bin:/opt/chef-workstation/embedded/bin:{{env.PATH}}" +KITCHEN_LOCAL_YAML = "kitchen.dokken.yml" diff --git a/resources/install.rb b/resources/install.rb index 2b16a845..d52f51cd 100644 --- a/resources/install.rb +++ b/resources/install.rb @@ -31,13 +31,13 @@ # Source property :source_version, String, - default: '2.8.5' + default: '2.8.13' property :source_url, String, default: lazy { "https://www.haproxy.org/download/#{source_version.to_f}/src/haproxy-#{source_version}.tar.gz" } property :source_checksum, String, - default: '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' + default: '13dc06a65b7705b94c843bda8b845edbb621bf45e8a9dc7db590d40ab920a9ce' property :source_target_cpu, String, default: lazy { node['kernel']['machine'] } @@ -51,7 +51,8 @@ default: true property :use_pcre, [true, false], - default: true + default: true, + description: 'Enable PCRE support (automatically selects PCRE or PCRE2 based on platform)' property :use_promex, [true, false], default: false @@ -96,6 +97,11 @@ def compile_make_boolean(bool) bool ? '1' : '0' end + + def pcre_make_flag + # Use PCRE2 for RHEL/CentOS/AlmaLinux/Rocky >= 10, PCRE for < 10 and other platforms + pcre_package_name.include?('pcre2') ? 'USE_PCRE2' : 'USE_PCRE' + end end action :install do @@ -146,7 +152,7 @@ def compile_make_boolean(bool) make_cmd << " CPU=#{new_resource.source_target_cpu}" if property_is_set?(:source_target_cpu) make_cmd << " ARCH=#{new_resource.source_target_arch}" if property_is_set?(:source_target_arch) make_cmd << " USE_LIBCRYPT=#{compile_make_boolean(new_resource.use_libcrypt)}" - make_cmd << " USE_PCRE=#{compile_make_boolean(new_resource.use_pcre)}" + make_cmd << " #{pcre_make_flag}=1" if new_resource.use_pcre make_cmd << " USE_OPENSSL=#{compile_make_boolean(new_resource.use_openssl)}" make_cmd << " USE_ZLIB=#{compile_make_boolean(new_resource.use_zlib)}" make_cmd << " USE_LINUX_TPROXY=#{compile_make_boolean(new_resource.use_linux_tproxy)}" @@ -158,6 +164,8 @@ def compile_make_boolean(bool) make_cmd << " LUA_INC=#{new_resource.lua_inc}" if property_is_set?(:lua_inc) make_cmd << " SSL_LIB=#{new_resource.ssl_lib}" if property_is_set?(:ssl_lib) make_cmd << " SSL_INC=#{new_resource.ssl_inc}" if property_is_set?(:ssl_inc) + # Add RPATH for custom SSL library to ensure runtime linking works correctly + make_cmd << " LDFLAGS=-Wl,-rpath,#{new_resource.ssl_lib}" if property_is_set?(:ssl_lib) extra_cmd = ' EXTRA=haproxy-systemd-wrapper' if new_resource.source_version.to_f < 1.8 bash 'compile_haproxy' do @@ -178,8 +186,7 @@ def compile_make_boolean(bool) home "/home/#{new_resource.user}" group new_resource.group expire_date '2050-12-31' if Chef::VERSION.to_f >= 18.0 - # rubocop:disable Lint/AmbiguousOperator - inactive -1 if Chef::VERSION.to_f >= 18.0 + inactive(-1) if Chef::VERSION.to_f >= 18.0 end end end diff --git a/spec/unit/recipes/install_spec.rb b/spec/unit/recipes/install_spec.rb index 577fd9e7..6b323b43 100644 --- a/spec/unit/recipes/install_spec.rb +++ b/spec/unit/recipes/install_spec.rb @@ -12,7 +12,7 @@ it { is_expected.to install_package('haproxy') } end - context 'compile HAProxy' do + context 'compile HAProxy on Ubuntu' do recipe do haproxy_install 'source' do use_libcrypt true @@ -24,10 +24,117 @@ end end before(:each) do - stub_command('/usr/sbin/haproxy -v | grep 2.8.5').and_return('2.8.5') + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return('2.8.13') end it { is_expected.to install_package(%w(libpcre3-dev libssl-dev zlib1g-dev libsystemd-dev)) } it { is_expected.not_to install_package('pcre-devel') } end + + context 'compile HAProxy on AlmaLinux 9' do + platform 'almalinux', '9' + + recipe do + haproxy_install 'source' + end + before(:each) do + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return('2.8.13') + end + + it { is_expected.to install_package(%w(pcre-devel openssl-devel zlib-devel systemd-devel tar)) } + it { is_expected.not_to install_package('pcre2-devel') } + end + + context 'compile HAProxy on AlmaLinux 10 (uses PCRE2)' do + platform 'almalinux', '10' + + recipe do + haproxy_install 'source' + end + before(:each) do + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return('2.8.13') + end + + it { is_expected.to install_package(%w(pcre2-devel openssl-devel zlib-devel systemd-devel tar)) } + it { is_expected.not_to install_package('pcre-devel') } + end + + context 'compile HAProxy on Amazon Linux (uses PCRE)' do + platform 'amazon', '2023' + + recipe do + haproxy_install 'source' + end + before(:each) do + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return('2.8.13') + end + + it { is_expected.to install_package(%w(pcre-devel openssl-devel zlib-devel systemd-devel tar)) } + it { is_expected.not_to install_package('pcre2-devel') } + end + + context 'compile HAProxy on Fedora (uses PCRE)' do + platform 'fedora', '32' + + recipe do + haproxy_install 'source' + end + before(:each) do + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return('2.8.13') + end + + it { is_expected.to install_package(%w(pcre-devel openssl-devel zlib-devel systemd-devel tar)) } + it { is_expected.not_to install_package('pcre2-devel') } + end + + context 'compile HAProxy with PCRE disabled' do + platform 'almalinux', '9' + + recipe do + haproxy_install 'source' do + use_pcre false + end + end + before(:each) do + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return(false) + end + + # When PCRE is disabled, we still install the package (for dependencies) + # but the make command should not include USE_PCRE or USE_PCRE2 flags + it { is_expected.to install_package(%w(pcre-devel openssl-devel zlib-devel systemd-devel tar)) } + it { is_expected.to run_bash('compile_haproxy') } + + it 'does not include PCRE flags in make command' do + bash_resource = chef_run.bash('compile_haproxy') + expect(bash_resource.code).to match(/make TARGET=linux-glibc/) + expect(bash_resource.code).to match(/USE_OPENSSL=1/) + expect(bash_resource.code).not_to match(/USE_PCRE2/) + expect(bash_resource.code).not_to match(/USE_PCRE=/) + end + end + + context 'compile HAProxy with custom OpenSSL' do + recipe do + haproxy_install 'source' do + use_openssl true + ssl_lib '/usr/local/openssl/lib' + ssl_inc '/usr/local/openssl/include' + end + end + before(:each) do + stub_command('/usr/sbin/haproxy -v | grep 2.8.13').and_return(false) + end + + it 'includes RPATH in the compilation command' do + expect(chef_run).to run_bash('compile_haproxy').with( + code: %r{LDFLAGS=-Wl,-rpath,/usr/local/openssl/lib} + ) + end + + it 'includes SSL_LIB and SSL_INC in the compilation command' do + expect(chef_run).to run_bash('compile_haproxy').with( + code: %r{SSL_LIB=/usr/local/openssl/lib SSL_INC=/usr/local/openssl/include} + ) + end + end end diff --git a/test/cookbooks/test/recipes/source_28.rb b/test/cookbooks/test/recipes/source_28.rb index 5ca0d236..5aee7b61 100644 --- a/test/cookbooks/test/recipes/source_28.rb +++ b/test/cookbooks/test/recipes/source_28.rb @@ -1,9 +1,9 @@ # renovate: datasource=endoflife-date depName=haproxy versioning=semver -version = '2.8.5' +version = '2.8.13' haproxy_install 'source' do source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" - source_checksum '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' + source_checksum '13dc06a65b7705b94c843bda8b845edbb621bf45e8a9dc7db590d40ab920a9ce' source_version version use_libcrypt true use_pcre true diff --git a/test/cookbooks/test/recipes/source_28_pcre2.rb b/test/cookbooks/test/recipes/source_28_pcre2.rb new file mode 100644 index 00000000..b8cbddb4 --- /dev/null +++ b/test/cookbooks/test/recipes/source_28_pcre2.rb @@ -0,0 +1,22 @@ +version = '2.8.5' + +# Test recipe for RHEL/CentOS platforms version 10 and above (uses PCRE2) +haproxy_install 'source' do + source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" + source_checksum '3f5459c5a58e0b343a32eaef7ed5bed9d3fc29d8aa9e14b36c92c969fc2a60d9' + source_version version + # Rely on auto-detection for PCRE2 on RHEL >= 10 + use_libcrypt true + use_openssl true + use_zlib true + use_linux_tproxy true + use_linux_splice true +end + +haproxy_config_global '' + +haproxy_config_defaults '' + +haproxy_service 'haproxy' do + action %i(create enable start) +end diff --git a/test/cookbooks/test/recipes/source_32.rb b/test/cookbooks/test/recipes/source_32.rb new file mode 100644 index 00000000..9d581f1c --- /dev/null +++ b/test/cookbooks/test/recipes/source_32.rb @@ -0,0 +1,23 @@ +# renovate: datasource=endoflife-date depName=haproxy versioning=semver +version = '3.2.7' + +haproxy_install 'source' do + source_url "https://www.haproxy.org/download/#{version.to_f}/src/haproxy-#{version}.tar.gz" + source_checksum '1f0ae9dfb0b319e2d5cb6e4cdf931a0877ad88e0090c46cf16faf008fbf54278' + source_version version + use_libcrypt true + use_pcre true + use_openssl true + use_zlib true + use_linux_tproxy true + use_linux_splice true +end + +haproxy_config_global '' + +haproxy_config_defaults '' + +haproxy_service 'haproxy' do + action :create + delayed_action %i(enable start) +end diff --git a/test/integration/source_3.2/controls/source_spec.rb b/test/integration/source_3.2/controls/source_spec.rb new file mode 100644 index 00000000..67a82c01 --- /dev/null +++ b/test/integration/source_3.2/controls/source_spec.rb @@ -0,0 +1 @@ +include_controls 'haproxy-common'